The document provides an overview of the Spring Security framework including its architecture, configuration, and usage. Key points:
- Spring Security adds authentication, authorization, and security features to web applications through configuration files and Java code.
- It uses filters, providers, and voters to handle authentication, provide a common interface, and make authorization decisions.
- Configuration involves setting up an authentication manager, providers, and access control for URLs.
- Dependencies are added through Maven and filters are defined in web.xml to secure web applications using Spring Security.
Automating Google Workspace (GWS) & more with Apps Script
Spring Security Framework Guide
1. Spring Security Framework
This is a reference document for software developers to understand/learn
Spring Security Framework.
Jayasree Perilakkalam
2. What is a Spring Security Framework? How is it
useful?
• Spring Security Framework adds the following capabilities to your web
application:
• Authentication
• Authorization
• Spring Security Framework provides protection against common security
issues like CSRF attack, Session Fixation attack, etc.
• Spring Security Framework provides a simple (requires just few
configuration files to set up a default login form/functionality) and a
standard way to set up user login functionality in a web application. Thus it
provides a framework that can quickly get authentication/authorization set
up on your web application.
• Spring Security handles application security for a web application.
3. Spring Security Architecture
• Reference: https://spring.io/guides/topicals/spring-security-architecture
• The main strategy interface for authentication is “AuthenticationManager” which only has
one method as shown below:
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
• An “AuthenticationManager” can do one of the following 3 things in its authenticate()
method:
• Return an “Authentication” (normally with authenticated=true) if it can verify that the
input represents a valid principal.
• Throw an “AuthenticationException” if it believes that the input represents an invalid
principal
• Return null if it can’t decide. “AuthenticationException” is a runtime exception.
• The most common implementation of “AuthenticationManager” is “ProviderManager”,
which delegates to a chain of “AuthenticationProvider” instances i.e. internally
“ProviderManager” iterates through a list of “AuthenticationProvider” instances.
4. Spring Security Architecture
• “AuthenticationProvider” instances are tried in order until one provides a non-null reponse. A
non-null response indicates that the particular “AuthenticationProvider” had the authority to
decide on the authentication and thus no further “AuthenticationProvider” is tried.
• If a subsequent “AuthenticationProvider” successfully authenticates the request, earlier
“AuthenticationException” is disregarded i.e. the successful authentication will be used.
• If no subsequent “AuthenticationProvider” returns a non-null response or a new
“AuthenticationException”, the last “AuthenticationException” will be used.
• If no “AuthenticationProvider” returns a non-null response or indicates it can even process an
“Authentication”, the “ProviderManager” will throw a “ProviderNotFoundException”.
• A parent “AuthenticationManager” can also be set and this will also be tried if none of the
configured “AuthenticationProvider” can perform the authentication.
• When “AuthenticationProvider” throws “AccountStatusExceprion”, no further
“AuthenticationProvider” is tried.
• Reference: https://docs.spring.io/spring-
security/site/docs/4.2.12.RELEASE/apidocs/org/springframework/security/authentication/Provid
erManager.html
5. Spring Security Architecture
**In-depth topic and can be ignored unless there is a specific requirement for it.
• “AuthenticationProvider” is a bit like “AuthenticationManager”, but it has an extra method to allow the caller
to query if it supports a given “Authentication” type or not.
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);
}
• “Class<?>” argument above is actually “Class<? extends Authentication>” (as it will only be asked if it
supports something that will be passed into the “authenticate()” method).
• “ProviderManager” has an optional parent “AuthenticationManager” which it can consult if all
“AuthenticationProvider” instances available return null. If the parent “AuthenticationManager” is not
available then it results in an “AuthenticationException”.
** Sometimes, an application has logical groups of protected resources (e.g. all web resources that match a
path pattern /api/**), and each group can have its own dedicated “AuthenticationManager”. Often each of
those is a “ProviderManager” and they share a parent “AutheticationManager”. The parent is then like a global
resource acting as a fallback for all providers.
6. Spring Security Architecture
• Spring Security provides some configuration helpers to quickly get “AuthnticationManager” set up in your
application.
• The most commonly used helper is “AuthenticationManagerBuilder” which is great for setting up in-
memory, JDBC or LDAP user details, or for adding a custom “UserDetailsService”. Following is an example of
configuring the global (parent) “AuthenticationManager”:
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
...
@Autowired
public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("dave")
.password("secret").roles("USER");
}
}
• When used in @Override of a method in the configurer as shown in the next slide,
“AuthenticationManagerBuilder” will be a local “AuthenticationManager” which is a child of the global one.
7. Spring Security Architecture
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Autowired
DataSource dataSource;
...
@Override
public void configure(AuthenticationManagerBuilder builder) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("dave")
.password("secret").roles("USER");
}
}
• In a Spring Boot application, the global one can be “@Autowired” into another bean, but this cannot be
done with a local one unless it’s exposed explicitly. Spring Boot provides a default global
“AuthenticationManager” with just one user unless you pre-empt it by providing your own bean of type
“AuthenticationManager”. The default is secure enough on its own.
• If a configuration that builds “AuthenticationManager” is required, do it locally to the resources that are
being protected and not worry about the global default.
8. Spring Security Architecture
• In most cases, “AuthenticationProvider” implementations will create “UserDetails”
object as “Principal” in the returned “Authentication”.
• From the security context, the username of the user logged in (i.e. the authenticated
user) is available. A sample code to get this information is as follows:
org.springframework.security.core.userdetails.User user =
(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
• The main strategy interface for authorization is “AccessDecisionManager”.
• There are three implementations provided by the framework for
“AccessDecisionManager” and all three delegate to a chain of “AccessDecisionVoter” (a
bit like “ProviderManager” delegates to a list of “AuthenticationProvider”).
• “AccessDecisionVoter” considers the “Authentication” object (representing a principal)
and the secure object which has been decorated with “ConfigAttributes” as indicated in
the “AccessDecisionVoter” interface methods in the next point/slide.
9. Spring Security Architecture
• The “AccessDecisionVoter” interface has the following methods:
boolean supports(ConfigAttribute attribute);
boolean supports(Class<?> clazz);
int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
• “object” is generic in the signatures of the methods in “AccessDecisionManager” and
“AccessDecisionVoter”. It represents anything that the user might want to access (a web
resource or a method in a Java class are the two most common cases)
• “ConfigAttribute” represents a decoration of the secure “object” with some metadata
that determine the level of permission required to access it. “ConfigAttribute” is an
interface with only one method which returns a String. This String encode in some way
the intention of the owner of the resource, expressing rules about who is allowed to
access it. A typical “ConfigAttribute” is the name of a user role (like “ROLE_ADMIN”,
“ROLE_USER” etc.), and they have special formats (like “ROLE_” prefix) or represent
expressions that need to be evaluated.
10. Spring Security Architecture
• Most people just use the default “AccessDecisionManager” which is
“AffirmativeBased” (a simple concrete implementation of
“AccessDecisionManager” that grants access if any “AccessDecisionVoter” returns
an affirmative response). Any customization tends to happen in the voters, either
adding new ones, or modifying the existing ones.
• It is very common to use “ConfigAttribute” that is a Spring Expression
Language(SpEL) expressions e.g. hasRole(“ROLE_USER”). This is supported by
“AccessDecisionVoter”. “AccessDecisionVoter” can handle the expressions and
create a context for them.
• More Reference: https://docs.spring.io/spring-security/site/docs/3.2.0.CI-
SNAPSHOT/reference/html/authz-arch.html
11. Spring Security Architecture
• Spring Security in the web tier (for UIs or HTTP back ends) is based on Servlet “Filter”.
• Spring Security doesn’t use servlets or any other servlet frameworks (such as Spring
MVC) internally, so it has no strong links to any particular web technology. It deals in
HttpServletRequest and HttpServletResponse and doesn’t care whether the requests
come from a browser, a web service client, an HttpInvoker or an AJAX application.
• The client sends a request to the app, and the container decides which filters and which
servlet apply to it based on the path of the request URI.
• At most one servlet can handle a single request, but filters form a chain. Filters are
ordered. A filter can veto the rest of the chain if it wants to handle the request itself. A
filter can also modify the request and/or response used in the downstream filters and
the servlet.
• Spring Security is installed as a single “Filter” in the chain and its concrete type is
“FilterChainProxy”.
12. Spring Security Architecture
• From the point of view of the container, Spring Security is a single filter, but inside
it there are additional filters (each playing a special role) as depicted below:
Spring Security Filters
Client
Filter
FilterChainProxy
Filter
Servlet
Filter
Filter
Filter
13. Spring Security Architecture
• Spring Security is installed in the container as “DelegatingFilterProxy” which does not have to be a Spring
@Bean. This proxy delegates to a “FilterChainProxy” which is always @Bean with name as
“springSecurityFilterChain”.
• web.xml will contain “DelegatingFilterProxy” definition with “filter-name” corresponding to a bean name in
Spring’s root application context. All the calls to “DelegatingFilterProxy” will then be delegated to that bean
(which is required to implement the standard Servlet Filter interface), by design.
• When web.xml contains “DelegatingFilterProxy” definition as shown below, all the calls to
“DelegatingFilterProxy” will be delegated to the bean with name as “springSecurityFilterChain” (which is of
concrete type “FilterChainProxy“ and implements the standard Servlet Filter interface).
<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>
14. Spring Security Architecture
• “FilterChainProxy” contains all the security logic arranged internally as a chain (or
chains) of filters. All the filters have the same API (they all implement the Filter
interface from the Servlet Spec) and they all have the opportunity to veto the rest
of the chain.
• There can be multiple filter chains managed by Spring Security at the same top
level (“FilterChainProxy” level) and all unknown to the container.
• The Spring Security filter (“FilterChainProxy”) contains a list of filter chains, and
dispatches the request to the first chain that matches it.
15. Spring Security Architecture
• The picture below shows dispatch happening based on matching the request’s
path. This is a very common way to match a request, but not the only way.
• The most important feature of this dispatch process is that only one chain ever
handles a request.
/foo/** /bar/** /**
/
FilterChainProxy
Filter
Filter
Filter
Filter
Filter
Filter
Filter
16. Spring Security Architecture
**In-depth topic and can be ignored unless there is a specific requirement for it.
• The fact that all the filters in Spring Security are unknown to the container is important, especially in a Spring
Boot application, where all @Bean of type “Filter” are registered automatically with the container. So if you
want to add a custom filter to the Spring Security chain, you need to either not make it a @Bean or wrap it
in “FilterRegistrationBean”that explicitly disables the container registration.
• Many applications have completely different access rules for one set of resources compared to another e.g.
an application that has a UI and a backing API might support cookie based authentication with a redirect to
login page for the UI part, and token-based authentication with a 401 response to un-authenticated requests
for the API parts. Each set of resources has its own “WebSecurityConfigurerAdapter” with a unique order
and its own request matcher. If the matching rules overlap, the earliest ordered filter chain will win.
**A vanilla Spring Boot application with no custom security configuration has several (say n) filter chains. The
first n-1 filter chains are there to just ignore static resource patterns like /css/**, /images/**, and the error
view /error etc. The last chain matches the catch all path /** and is more active , containing logic for
authentication, authorization, exception handling, session handling, header writing, etc. There are a total of 11
filters in this chain by default, but it is not necessary for users to concern themselves with which filters are
used and when.
17. Spring Security Architecture
• A Spring Security filter chain (or equivalently a WebSecurityConfigurerAdapter) has a request matcher that is
used for deciding whether to apply it to the HTTP request. Once the decision is made to apply a particular
chain, no others are applied. But, within the filter chain, there can be more fine grained control of
authorization by setting additional matchers in the “HttpSecurity” configure. A sample is as follows:
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10) // applicable for a Spring Boot application
public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/foo/**").authorizeRequests()
.antMatchers("/foo/bar").hasRole("BAR")
.antMatchers("/foo/spam").hasRole("SPAM")
.anyRequest().isAuthenticated();
}
}
Note: “SecurityProperties.BASIC_AUTH_ORDER” above is the predefined order for the fallback/default filter chain in a
Spring Boot application (the one with the /** request matcher ). So to order the above filter chain before this
fallback/default filter chain, “@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)” has been added in the above
configuration.
18. Maven Dependency
• Add the following in the pom.xml file to add Spring Security in your Spring application:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
19. A sample XML based Configuration
• Add the following in the web.xml file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springsecurity-servlet.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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
20. A sample XML based Configuration
• Add the following in the Spring Bean configuration file (“springsecurity-servlet.xml” as defined in the
previous slide):
<xml version="1.0" encoding="UTF-8">
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:securirty="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-
3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-
3.1.xsd">
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="connectionCachingEnabled" value="true"/>
</bean>
<context:property-placeholder location="classpath:jdbc.properties"/>
Contd…
21. A sample XML based Configuration
Contd…
<bean id="encoder" class="org.springframework.security.authetication.encoding.Md5PasswordEncoder"></bean>
<!-- public pages i.e. pages not requiring aithentication -->
<security:http pattern="/public/* security="none" />
<security:http pattern="/images/*" security="none" />
<!-- pages requiring aithentication -->
<security:http auto-config="true">
<security-intercept-url pattern="/**" access="ROLE_ADMIN" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:password-encoder ref="encoder">
<security:salt-source system-wide="somesalt" />
</security:password-encoder>
Contd…
22. A sample XML based Configuration
Contd…
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username as username, password as password, 1 as enabled from
user_authentication where username=?"
authorities-by-username-query="select u1.username, u2.role from user_authentication u1,
user_authorization u2 where u1.user_id=u2.user_id and u1.username=?" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
Note: A default login form is available/added via Spring Security when the above configuration is completed.
23. A sample Java based Configuration
• A similar configuration can be achieved with a Java Configuration using the following steps.
• Add the following in your Spring application to add “springSecurityFilterChain”. This registers
“DelegatingFilterProxy” to use the “springSecurityFilterChain” before any other registered “Filter”.
@Order(2)
public class MySecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer {
}
• Subclasses of “AbstractDispatcherServletInitializer” need to register their filters before any other “Filter”.
This means that we will typically need to ensure subclasses of “AbstractDispatcherServletInitializer” are
invoked first. This can be done by ensuring @Order for subclass of “AbstractDispatcherServletInitializer” is
less than @Order for subclass of “AbstractSecurityWeApplicationInitializer” as shown in the sample
configuration in the next slide.
24. A sample Java based Configuration
@Order(1)
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context and register all config classes
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
• References:
• https://docs.spring.io/spring-security/site/docs/current/guides/html5/helloworld-javaconfig.html
• https://docs.spring.io/spring-
security/site/docs/4.2.12.RELEASE/apidocs/org/springframework/security/web/context/AbstractSecurit
yWebApplicationInitializer.html
25. A sample Java based Configuration
• A sample Spring Security (filter chain) configuration is as follows:
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
// Spring Security should completely ignore URLs starting with /resources/
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
.hasRole("USER").and()
// Possibly more configuration ...
.formLogin() // enable form based log in
// set permitAll for all URLs associated with Form Login
.permitAll();
}
Contd…
26. A sample Java based Configuration
Contd…
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
// enable in memory based authentication with a user named "user" and "admin"
.inMemoryAuthentication().withUser("user").password("password").roles("USER")
.and().withUser("admin").password("password").roles("USER", "ADMIN");
}
}
• @EnableWebSecurity is used to define Spring Security configuration in any “WebSecurityConfigurer” or
more likely by extending “WebSecurityConfigurerAdapter” and overriding individual methods as shown
above.
• Reference: https://docs.spring.io/spring-
security/site/docs/current/api/org/springframework/security/config/annotation/web/configuration/Enable
WebSecurity.html
27. Conclusion
• This is a reference guide for understanding Spring Security concepts and for learning how
to implement Spring Security in your web application.
• Any questions/suggestions/comments are welcome via the comments section below.
• Some References are as follows:
• Source Code: https://github.com/spring-projects/spring-
security/blob/c1db1aad91837d571ab3d621c8e470d67c7635c6/config/src/main/java
/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
• https://docs.spring.io/spring-
security/site/docs/4.2.12.RELEASE/apidocs/org/springframework/security/web/cont
ext/AbstractSecurityWebApplicationInitializer.html
Thank you