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
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);
}
}
}
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

