Home » Open Source » Spring Security 3.1 – Concepts

Spring Security 3.1 – Concepts

In this post I shall give a brief overview about Core Concepts in Spring Security. Example used in this post is simple, however for sake of completeness I have uploaded it here

Overview

Spring security can be used to add security around your existing/new web application.  Spring leverages use of doFilter() method from servlet api, to intercept the incoming requests and takes appropriate action. Spring security provides a  class DelegatingFilterProxy, which acts as bridge between your application and the security components. Below diagram represents a conceptual overview Of important components involved during bootstrap

SpringSecurity- BootStrapping

SpringSecurity- BootStrapping

Bootstrapping application with Spring Security

To bootstrap an application using Spring security, entries for following must be made in web.xml

1. DelegatingFilterProxy
2. spring-security config file


   <context-param>
        <param-name>contextConfigLocation</param-name>
         <param-value>
            /WEB-INF/spring-security.xml
           /WEB-INF/applicationContext.xml
         </param-value>
     </context-param>
 <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>

Below is an example of very minimalistic spring security file .


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
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.1.xsd">

<http auto-config="true" use-expressions="true">
        <intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/>
        <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
        <intercept-url pattern="/" access="permitAll"/>
         <logout invalidate-session="true"   logout-success-url="/"  logout-url="/logout"/>
</http>

<authentication-manager alias="authenticationManager">
       <authentication-provider>
        <user-service>
           <user authorities="ROLE_USER" name="user1" password="password"/>
           <user authorities="ROLE_ADMIN" name="admin" password="admin"/>
          </user-service>
       </authentication-provider>
     </authentication-manager>
</beans:beans>

Essentially in above configuration we are doing two things

  • Declaring URL’s for which we want to assign access rules via intercept-url tag
  • Provide means of authenticating users via authentication-manager tag

When the root application context loads, it initializes all the components needed for Spring security.
The elements defined in spring-security configuration are parsed via  SecurityNamespaceHandler which in turn uses HttpSecurityBeanDefinitionParser to build default filters. Below are important actions performed by HttpSecurityBeanDefinitionParser

1. Creates FilterChainProxy
2. Assigns alias springSecurityFilterChain ( note above, we define this in web.xml) to FilterChainProxy
3. Creates Filter Chains and orders them
4. Stores the Filter chains in FilterChainProxy

For a spring security file shown in example, below are filters created in this particular order.

  • SecurityContextPersistenceFilter
  • LogoutFilter
  • UserNamePasswordAuthenticationFilter
  • DefaultLoginPageGeneratingFilter
  • BasicAuthenticationFilter
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • AnonymousAuthenticationFilter
  • SessionManagementFilter
  • ExceptionTranslationFilter
  • FilterSecurityInterceptor

SecurityContextPersistenceFilter, ExceptionTranslationFilter and FilterSecurityIntercept are always created with http tag. These are fixed and cannot be changed

Please take a look here for excellent article on security namespaces

 DelegatingFilterProxy and FilterChainProxy

DelegatingFilterProxy  extends GenericFilterBean. Internally it stores instance of FilterChainProxy and delgates requests to it.

FilterChanProxy also extends GenericFilterBean. It essentially maintains list of filters and iterates through each of them when doFilter() is executed.( Refer code below)


public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (currentPosition == size) {
     if (logger.isDebugEnabled()) {
          logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
          + " reached end of additional filter chain; proceeding with original chain");
      }
       // Deactivate path stripping as we exit the security filter chain
       this.firewalledRequest.reset();
        originalChain.doFilter(request, response);
} else {
       currentPosition++;
       Filter nextFilter = additionalFilters.get(currentPosition - 1);
       if (logger.isDebugEnabled()) {
          logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition + " of "
          + size + " in additional filter chain; firing Filter: '"
          + nextFilter.getClass().getSimpleName() + "'");
        }
    nextFilter.doFilter(request, response, this);
    }
   }
}

FilterChainProxy

General convention is to define DelegatingFilterProxy in web.xml, however you could directly define FilterChainProxy in web.xml, if  you need more control. However per Spring documentation, this is not recommended .

RoleBasedAuthorization

In our demo example we have very simplistic URL based authentication. We are authenticating users based on roles. Below is section from configuration file

     <authentication-manager alias="authenticationManager">
         <authentication-provider>
            <user-service>
               <user authorities="ROLE_USER" name="user1" password="password"/>
               <user authorities="ROLE_ADMIN" name="admin" password="admin"/>
           </user-service>
       </authentication-provider>
     </authentication-manager>

Things to note

AuthenticationManager – Manages authentication requests. Internally it uses AuthenticationProvider (DaoAuthenticationProvider) and UserDetailService (InMemoryUserDetailsManager) to accomplish authentication.

We have defined couple of users in config file, for demo purposes. In real implementation these should come from database.

There are couple of other important interfaces

Authentication – Stores information about User Credentials and Authorities (role which user has).

Principal – User in consideration is called as Principal in context of Spring Security.

Below are some of the important steps in typical access workflow and how all the components interact with each other

  • doFilter() in DelegatingFilterProxy is invoked, which in turn involves FilterChainProxy, which internally invokes chain of filters.
  • FilterSecurityInterceptor ( last filter in chain above) is invoked
  • FilterSecurityInterceptor performs authentication
    • Gets Authentication Object from SecurityContextHolder
    • If previously authenticated returns Authentication object
    • If not authenticated, create Authentication using AuthenticationManager
    • returns Authentication
  • Requests  AccessDecisionManager to decide based on – Authentication , URL to be accessed and access rules associated with the URL.
  • AccessDecisionManager throws AccessDeniedException if principal doesn’t have access.
    • Exception is handled by ExceptionTranslationFilter.
    • If Authentication Object is anonymous, user is redirected to Login Page
    • If User has Authentication Object( but doesnt have appropriate authorities/roles) , then user is redirect to Access Denied page .
  • If no exception is thrown then appropriate status is returned and request processing is continued.

AccessDecisionManager  is the interface which facilitates in making decision if Principal should be given access or not. By default AffirmativeBased decision manager is used . Below are steps taken by AffirmativeBased  decision manager to make a decision.

  • Loops through each  AccessDecisionVoter
  • If any of them returns affirmative, access is granted.
  • AccessDecisionManager denies a request if there was a deny vote and no affirmative vote.
  • If all the voters abstain from voting, decision is based on property, allowIfAllAbstainDecisions which defaults to false.

AccessDecisionVoter is interface which has vote method. It uses SPeL to decide whether the principal has access to resource. For above configuration, WebExpressionVoter  is used [ as we have set attribute “use-expressions” to “true“].

Below are steps through which WebExpressionVoter makes decision

  • Gets authorizationExpression
  • Creates EvaluationContext, set the root Object
  • Evaluates expression in context as boolean value and returns the result

In case of SPeL, generally a root object and context is created. Then the expression is evaluated in that particular context. In our scenario below are sequence of actions

  • Expression which will be evaluated is – “permitAll” or “hasRole(‘ROLE_USER’)” or hasRole(‘ROLE_ADMIN’).These are defined in access attribute in intercept_url tag.
  • For every request, Root Object- WebSecurityExpressionRoot is created. This encapsulates Authentication object, which has information about authorities principal has
    • So if user is admin, authorities will be ROLE_ADMIN
    • if its general user, authorities will be ROLE_USER
  • WebSecurityExpressionRoot is subclass of SecurityExpressionRoot and has several predicates which are used in evaluation . Below are couple of examples
    • permitAll  – always returns true
    • hasRole(role) – Iterates through authorities and returns true if role is present
  • In this particular situation,
    • if user is accessing URL, for which access attribute is “permitAll” then SecurityExpressionRoot returns true
    •  If user is accessing URL, for which access attributeis “hasRole(‘ROLE_USER’)” then SecurityExpressionRoot returns true if ROLE_USER  is present in authorities of  authentication object .

For good overview on SPeL please take a look at Dzone refcardz.

That completes an overview of core concepts in Spring Security. Springsource provides good documentation security. In addition Spring Security 3 by Peter Mularein is a good resource .

In my next article I shall discuss ACL components in Spring Security

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: