Wednesday, April 20, 2011

Spring Security

Spring Security provides a very good security solution(s), handling authentication and authorization at the web request level and at the method invocation level by using the features of Dependency Injection (DI) & Aspect Oriented techniques.
Spring security targets two areas viz. 1. Authentication & 
                                                            2. Authorization

1.  Authentication: - is the assurance that the user is the actual user he is claiming to be.
E.g. Particular user logs into the application through his credentials means get authenticated himself.

Spring Supports following types of Authentication :
a.      Http Basic Authentication
b.      Form Based Authentication 

      2.   Authorization: - is the assurance that the user is allowed to access only those resources that he is authorized to use.
E.g. Admin of the any website have access for some parts/pages & normal user done have access to these pages.

For authorization spring targets following areas,
a.      Authorizing web requests
b.      Authorizing whether methods can be invoked
c.       Authorizing access to individual domain objects
Following jar’s need to be present in the class path of the project.
      1.  Core => spring-security-core.jar
      2.  Web => spring-security-web.jar
      3.  Config => spring-security-config.jar

Namespace Configuration :-
Spring Security comes with a security-specific namespace which simplifies security configuration in Spring. This new namespace, along with some default behavior, reduces a typical security configuration from over 100 lines of XML to a dozen or so. The namespace configuration of the Spring provides a shortcut that hides much of complexity of the framework.
E.g.
<beans xmlns="http://www.springframework.org/schema/beans"             xmlns:security="http://www.springframework.org/schema/security"             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             xsi:schemaLocation="http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd             http://www.springframework.org/schema/security             http://www.springframework.org/schema/security/spring-security-3.0.xsd">
            <security: …..>…..</security:…>
</beans>
For web security in Spring, we must set up the servlet filters that provide the various security features.
Proxying servlet filters :-
<filter>
    <filter-name>springSecurityFilterChain</filter-name>                        <filter-class>
org.springframework.web.filter.DelegatingFilterProxy </filter-class>
</filter>
<filter-mapping>
<filter-name> springSecurityFilterChain </filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In above code snippet DelegatingFilterProxy deligates the control to a filter implementation which is defined as bean named springSecurityFilterChain. This bean is an infrastructural  bean to handle namespace configurations. Once this configuration is done, all the incoming requests enter the spring framework for security check. This special filter, by itself will not do much, it deligates to an implementation of javax.servlet.Filter which is registered as <bean> in spring application context.
It is not possible to inject beans into the servlet filters registered into the web.xml. But by using DelegatingFilterProxy, we can we can configure the actual filters.
<filter-name> given to the DelegatingFilterProxy is very significant & useful. This name is used to look up the filter bean from the Spring application context. Spring Security will automatically create a filter bean whose ID is springSecurityFilterChain, so that’s the name, given to DelegatingFilterProxy in web.xml.
springSecurityFilterChain bean itself is another special filter known as FilterChainProxy. It’s a single filter which chains one or more filters. Spring Security will automatically create those beans for us when we configure the <http> element.
Security Configuration :-
We can define security configuration file as applicationContext-security.xml & this file need to be loaded in web.xml. This is done by ContextLoadListner.
Following snippet needs to be added in web.xml before security filter definition.

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>WEB-INF/applicationContext-security.xml</param-value>
</context-param>
<listener>
     <listener-class>
               org.springframework.web.context.ContextLoaderListener
     </listener-class>
</listener>

applicationContext-security.xml
Whenever namespace configuration is used, spring-config.jar needs to be in class path. The first line in this file should be like,
<beans xmlns="http://www.springframework.org/schema/security"
  xmlns:bean="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
    ...
</beans>

The minimal namespace configuration like:-
Following only three lines of XML configures spring security to intercept all requests for all URL’s and restrict access to only authenticated users who have  “ROLE_USER” role. This <http> element automatically set up FilterChainProxy & all the filter beans in the chain shown in following diagram.
<http auto-config=”true”>
 <intercept-url pattern=”/**” access=”ROLE_USER” />
</http>

<authentication-manager>
    <authentication-provider>
      <user-service>
        <user name="testadmin" password="testadminpassword"
                      authorities="ROLE_USER, ROLE_ADMIN" />
        <user name="testuser" password="testuserpassword"
             authorities="ROLE_USER" />
      </user-service>
    </authentication-provider>
</authentication-manager>
The attribute auto-config=”true" defines three elements <form-login/>, <http-basic/> and <logout>.The default configuration always chooses http-basic authentication model. If the model needs to be changed to the form-login model, then the following configuration is needed.
<http auto-config=”true”>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
      <intercept-url pattern="/**" access="ROLE_USER" />
           <form-login login-page=”/login.jsp”/>
</http>
This above configuration is done to enable form-login authentication model where the login page is login.jsp. Note that in the intercept tag, pattern for login.jsp is given and access rule is defined as IS_AUTHENTICATED_ANONYMOUSLY. That means login.jsp is not checked for security, which makes sense as login.jsp is the starting point from where the user is authenticated.
The tag <authentication-manager> processes the authentication information; <authentication-provider> defines the credential information and the roles given to each user (authentication information).
Spring Security framework is a chain of filters, with each filter having certain responsibility.
 In following section the namespace configuration to bean configuration to understand the flow and responsibility of each filter.
The <http> block in namespace configuration invokes the chain of filters. DelegatingFilterProxy that is defined in web.xml invokes the FilterChainProxy class which in turn invokes the chain of filters defined for each URL pattern.
The chain of filters that FilterChainProxy calls are shown below:



To override the default behavior of login page, need to configure <form-login> element,
<http auto-config="true" use-expressions="false">
<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
</http>

login attribute specifies a new context-relative URL for the login page & it will reside at /login which is ultimately handled by a Spring MVC controller.
If authentication fails, the authentication-failure-url attribute is set to send the user back to the same login page.

Intercepting requests : -
<intercept-url> Element is the first line of defense in request level security. Its pattern attribute is given a URL pattern that will be matched against incoming requests. If any requests match the pattern, then that <intercept-url>’s security rules will be applied.
<intercept-url pattern="/**" access="ROLE_USER" />
/** => indicating that we want all requests, regardless of the URL, to require ROLE_USER access
For area for admin & restricted to others’ in this case following snippet need to put before previous <intercept_url>
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
This will restricts the access to the /admin of site’s hierarchy to users’ with ROLE_ADMIN authority. We can use many <intercept-url> entries as we require securing various paths of application.
<intercept-url> rules are are applied top to bottom.
SECURING WITH SPRING EXPRESSIONS: -
Spring Expression Language (SpEL) as an advanced technique for wiring bean properties.
To enable it, we must set the use-expressions attribute of <http> to true:
<http auto-config="true" use-expressions="true">
            ……....
</http>
Use of SpEL expression:-
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
Securing view-level elements :-
To support security in the view layer, Spring Security comes with a JSP tag library. This tag library is small and includes only three tags,
<security:accesscontrollist> - Allows the body of the tag to be rendered if the currently authenticated user has one of the stipulated permissions in the specified domain object
<security:authentication> - Accesses properties of the current user’s authentication object
<security:authorize> - Allows the body of the tag to be rendered if a specified security constraint has been met

To use the JSP tag library, we’ll need to declare it in the JSP file,
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

Accessing authentication details :-
This tag library provide convenient access to user’s authentication information,
e.g. Welcome XYZ ! …. At the header of application.
Welcome <security:authentication property="principal.username" />!

No comments: