Spring Security Reference
Spring Security Reference
4.0.2.RELEASE
Copyright 2004-2015
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee
for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Table of Contents
................................................................................................................................................ xv
I. Preface ................................................................................................................................... 1
II. Getting Started ....................................................................................................................... 3
1. Introduction .................................................................................................................... 4
1.1. What is Spring Security? ..................................................................................... 4
1.2. History ................................................................................................................ 6
1.3. Release Numbering ............................................................................................. 6
1.4. Getting Spring Security ........................................................................................ 7
Usage with Maven ............................................................................................. 7
Maven Repositories .................................................................................... 7
Spring Framework Bom .............................................................................. 8
Gradle ............................................................................................................... 8
Gradle Repositories .................................................................................... 8
Using Spring 4.0.x and Gradle .................................................................... 9
Project Modules ................................................................................................. 9
Core - spring-security-core.jar ..................................................................... 9
Remoting - spring-security-remoting.jar ...................................................... 10
Web - spring-security-web.jar .................................................................... 10
Config - spring-security-config.jar .............................................................. 10
LDAP - spring-security-ldap.jar .................................................................. 10
ACL - spring-security-acl.jar ...................................................................... 10
CAS - spring-security-cas.jar ..................................................................... 10
OpenID - spring-security-openid.jar ............................................................ 10
Checking out the Source .................................................................................. 10
2. Whats new in Spring Security 4.0 ................................................................................. 12
2.1. Features ............................................................................................................ 12
2.2. Migrating from 3.x to 4.x .................................................................................... 12
3. Java Configuration ....................................................................................................... 14
3.1. Hello Web Security Java Configuration ............................................................... 14
AbstractSecurityWebApplicationInitializer ........................................................... 15
AbstractSecurityWebApplicationInitializer without Existing Spring ......................... 15
AbstractSecurityWebApplicationInitializer with Spring MVC ................................. 16
3.2. HttpSecurity ....................................................................................................... 16
3.3. Java Configuration and Form Login .................................................................... 17
3.4. Authorize Requests ........................................................................................... 18
3.5. Handling Logouts ............................................................................................... 19
LogoutHandler .................................................................................................. 20
LogoutSuccessHandler ..................................................................................... 20
Further Logout-Related References ................................................................... 20
3.6. Authentication .................................................................................................... 21
In Memory Authentication ................................................................................. 21
JDBC Authentication ......................................................................................... 21
LDAP Authentication ......................................................................................... 21
3.7. Multiple HttpSecurity .......................................................................................... 22
3.8. Method Security ................................................................................................ 23
EnableGlobalMethodSecurity ............................................................................. 23
GlobalMethodSecurityConfiguration ................................................................... 24
4.0.2.RELEASE
Spring Security
iii
4.0.2.RELEASE
Spring Security
25
26
26
27
27
27
28
29
30
30
30
31
32
32
32
32
32
33
34
34
35
35
35
37
37
37
39
39
39
39
41
41
41
42
42
43
43
43
44
44
44
44
45
46
46
46
46
46
47
48
iv
Summary .........................................................................................................
7.3. Authentication ....................................................................................................
What is authentication in Spring Security? .........................................................
Setting the SecurityContextHolder Contents Directly ...........................................
7.4. Authentication in a Web Application ....................................................................
ExceptionTranslationFilter .................................................................................
AuthenticationEntryPoint ...................................................................................
Authentication Mechanism ................................................................................
Storing the SecurityContext between requests ...................................................
7.5. Access-Control (Authorization) in Spring Security ................................................
Security and AOP Advice .................................................................................
Secure Objects and the AbstractSecurityInterceptor ...........................................
What are Configuration Attributes? ............................................................
RunAsManager ........................................................................................
AfterInvocationManager ............................................................................
Extending the Secure Object Model ..........................................................
7.6. Localization .......................................................................................................
8. Core Services ..............................................................................................................
8.1. The AuthenticationManager, ProviderManager and AuthenticationProvider ............
Erasing Credentials on Successful Authentication ...............................................
DaoAuthenticationProvider ................................................................................
8.2. UserDetailsService Implementations ...................................................................
In-Memory Authentication .................................................................................
JdbcDaoImpl ....................................................................................................
Authority Groups ......................................................................................
8.3. Password Encoding ...........................................................................................
What is a hash? ...............................................................................................
Adding Salt to a Hash ......................................................................................
Hashing and Authentication ..............................................................................
IV. Testing ...............................................................................................................................
9. Testing Method Security ...............................................................................................
9.1. Security Test Setup ...........................................................................................
9.2. @WithMockUser ................................................................................................
9.3. @WithUserDetails ..............................................................................................
9.4. @WithSecurityContext .......................................................................................
10. Spring MVC Test Integration .......................................................................................
10.1. Setting Up MockMvc and Spring Security ..........................................................
10.2. SecurityMockMvcRequestPostProcessors ..........................................................
Testing with CSRF Protection ...........................................................................
Running a Test as a User in Spring MVC Test ...................................................
Running as a User in Spring MVC Test with RequestPostProcessor ....................
Running as a User in Spring MVC Test with Annotations ............................
Testing HTTP Basic Authentication ...................................................................
10.3. SecurityMockMvcRequestBuilders .....................................................................
Testing Form Based Authentication ...................................................................
Testing Logout .................................................................................................
10.4. SecurityMockMvcResultMatchers ......................................................................
Unauthenticated Assertion ................................................................................
Authenticated Assertion ....................................................................................
V. Web Application Security ......................................................................................................
4.0.2.RELEASE
Spring Security
48
48
48
51
51
52
52
52
52
53
53
54
54
54
55
56
56
58
58
59
59
59
60
60
61
61
61
61
62
63
64
64
65
66
66
68
68
68
68
69
69
70
70
71
71
71
71
72
72
73
4.0.2.RELEASE
Spring Security
74
74
74
75
76
76
77
77
79
79
80
80
80
81
81
82
82
83
84
84
84
84
84
85
85
85
85
85
86
87
87
88
88
88
88
89
91
91
91
92
92
92
93
94
94
94
95
95
95
96
vi
17.
18.
19.
20.
4.0.2.RELEASE
Spring Security
vii
4.0.2.RELEASE
Spring Security
121
123
124
124
124
124
125
126
126
126
127
127
129
129
129
129
132
132
132
133
133
134
134
135
135
136
137
138
138
138
140
143
143
143
144
144
144
144
144
145
145
146
146
146
146
147
147
147
148
148
viii
27.
28.
29.
30.
31.
32.
4.0.2.RELEASE
Spring Security
148
149
149
149
149
149
149
149
150
151
151
152
153
153
153
154
154
154
155
155
157
157
157
157
157
158
158
158
159
160
161
161
161
161
163
163
165
166
166
167
167
170
170
170
170
172
172
172
174
174
ix
4.0.2.RELEASE
Spring Security
174
174
174
175
175
175
175
176
176
177
178
179
179
179
180
181
181
181
182
183
184
185
186
186
186
187
187
187
189
190
191
192
193
193
193
193
193
195
195
196
196
196
196
196
196
197
197
197
197
197
4.0.2.RELEASE
Spring Security
197
197
197
198
198
198
198
198
199
199
199
199
199
199
199
199
199
200
200
200
200
200
200
200
200
201
201
201
202
202
202
202
202
202
202
202
203
203
203
203
203
203
204
204
204
205
205
205
205
205
xi
<openid-attribute> ...........................................................................................
Parent Elements of <openid-attribute> .....................................................
<openid-attribute> Attributes ....................................................................
<port-mappings> .............................................................................................
Parent Elements of <port-mappings> .......................................................
Child Elements of <port-mappings> .........................................................
<port-mapping> ..............................................................................................
Parent Elements of <port-mapping> .........................................................
<port-mapping> Attributes .......................................................................
<remember-me> .............................................................................................
Parent Elements of <remember-me> .......................................................
<remember-me> Attributes ......................................................................
<request-cache> Element ...............................................................................
Parent Elements of <request-cache> .......................................................
<request-cache> Attributes ......................................................................
<session-management> ..................................................................................
Parent Elements of <session-management> .............................................
<session-management> Attributes ...........................................................
Child Elements of <session-management> ...............................................
<concurrency-control> .....................................................................................
Parent Elements of <concurrency-control> ...............................................
<concurrency-control> Attributes ..............................................................
<x509> ...........................................................................................................
Parent Elements of <x509> .....................................................................
<x509> Attributes ...................................................................................
<filter-chain-map> ...........................................................................................
<filter-chain-map> Attributes ....................................................................
Child Elements of <filter-chain-map> .......................................................
<filter-chain> ..................................................................................................
Parent Elements of <filter-chain> .............................................................
<filter-chain> Attributes ...........................................................................
<filter-security-metadata-source> .....................................................................
<filter-security-metadata-source> Attributes ..............................................
Child Elements of <filter-security-metadata-source> ..................................
38.2. WebSocket Security .......................................................................................
<websocket-message-broker> .........................................................................
<websocket-message-broker> Attributes ..................................................
Child Elements of <websocket-message-broker> ......................................
<intercept-message> .......................................................................................
Parent Elements of <intercept-message> .................................................
<intercept-message> Attributes ...............................................................
38.3. Authentication Services ..................................................................................
<authentication-manager> ...............................................................................
<authentication-manager> Attributes ........................................................
Child Elements of <authentication-manager> ............................................
<authentication-provider> ................................................................................
Parent Elements of <authentication-provider> ...........................................
<authentication-provider> Attributes .........................................................
Child Elements of <authentication-provider> .............................................
<jdbc-user-service> .........................................................................................
4.0.2.RELEASE
Spring Security
205
205
205
206
206
206
206
206
206
206
206
206
207
207
207
207
207
208
208
208
208
208
209
209
209
209
209
209
209
210
210
210
210
210
210
210
211
211
211
211
211
212
212
212
212
212
212
213
213
213
xii
4.0.2.RELEASE
Spring Security
213
214
214
214
214
214
214
214
214
214
215
215
215
215
215
215
215
216
216
216
216
216
217
217
217
217
217
217
217
217
217
217
217
217
218
218
218
218
218
218
218
218
218
218
219
219
219
219
219
220
xiii
4.0.2.RELEASE
Spring Security
220
221
221
221
221
221
221
221
223
223
224
224
224
225
225
226
226
226
xiv
Spring Security is a powerful and highly customizable authentication and access-control framework. It
is the de-facto standard for securing Spring-based applications.
4.0.2.RELEASE
Spring Security
xv
Part I. Preface
Spring Security provides a comprehensive security solution for Java EE-based enterprise software
applications. As you will discover as you venture through this reference guide, we have tried to provide
you a useful and highly configurable security system.
Security is an ever-moving target, and its important to pursue a comprehensive, system-wide approach.
In security circles we encourage you to adopt "layers of security", so that each layer tries to be as secure
as possible in its own right, with successive layers providing additional security. The "tighter" the security
of each layer, the more robust and safe your application will be. At the bottom level youll need to deal
with issues such as transport security and system identification, in order to mitigate man-in-the-middle
attacks. Next youll generally utilise firewalls, perhaps with VPNs or IP security to ensure only authorised
systems can attempt to connect. In corporate environments you may deploy a DMZ to separate publicfacing servers from backend database and application servers. Your operating system will also play
a critical part, addressing issues such as running processes as non-privileged users and maximising
file system security. An operating system will usually also be configured with its own firewall. Hopefully
somewhere along the way youll be trying to prevent denial of service and brute force attacks against
the system. An intrusion detection system will also be especially useful for monitoring and responding to
attacks, with such systems able to take protective action such as blocking offending TCP/IP addresses in
real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured to minimize
the permissions granted to different Java types, and then your application will add its own problem
domain-specific security configuration. Spring Security makes this latter area - application security much easier.
Of course, you will need to properly address all security layers mentioned above, together with
managerial factors that encompass every layer. A non-exhaustive list of such managerial factors would
include security bulletin monitoring, patching, personnel vetting, audits, change control, engineering
management systems, data backup, disaster recovery, performance benchmarking, load monitoring,
centralised logging, incident response procedures etc.
With Spring Security being focused on helping you with the enterprise application security layer, you will
find that there are as many different requirements as there are business problem domains. A banking
application has different needs from an ecommerce application. An ecommerce application has different
needs from a corporate sales force automation tool. These custom requirements make application
security interesting, challenging and rewarding.
Please read Part II, Getting Started, in its entirety to begin with. This will introduce you to the framework
and the namespace-based configuration system with which you can get up and running quite quickly.
To get more of an understanding of how Spring Security works, and some of the classes you might need
to use, you should then read Part III, Architecture and Implementation. The remaining parts of this
guide are structured in a more traditional reference style, designed to be read on an as-required basis.
Wed also recommend that you read up as much as possible on application security issues in general.
Spring Security is not a panacea which will solve all security issues. It is important that the application
is designed with security in mind from the start. Attempting to retrofit it is not a good idea. In particular,
if you are building a web application, you should be aware of the many potential vulnerabilities such
as cross-site scripting, request-forgery and session-hijacking which you should be taking into account
from the start. The OWASP web site (http://www.owasp.org/) maintains a top ten list of web application
vulnerabilities as well as a lot of useful reference information.
We hope that you find this reference guide useful, and we welcome your feedback and suggestions.
1. Introduction
1.1 What is Spring Security?
Spring Security provides comprehensive security services for Java EE-based enterprise software
applications. There is a particular emphasis on supporting projects built using The Spring Framework,
which is the leading Java EE solution for enterprise software development. If youre not using Spring for
developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity
with Spring - and in particular dependency injection principles - will help you get up to speed with Spring
Security more easily.
People use Spring Security for many reasons, but most are drawn to the project after finding the security
features of Java EEs Servlet Specification or EJB Specification lack the depth required for typical
enterprise application scenarios. Whilst mentioning these standards, its important to recognise that they
are not portable at a WAR or EAR level. Therefore, if you switch server environments, it is typically a lot
of work to reconfigure your applications security in the new target environment. Using Spring Security
overcomes these problems, and also brings you dozens of other useful, customisable security features.
As you probably know two major areas of application security are "authentication" and "authorization" (or
"access-control"). These are the two main areas that Spring Security targets. "Authentication" is the
process of establishing a principal is who they claim to be (a "principal" generally means a user, device
or some other system which can perform an action in your application)."Authorization" refers to the
process of deciding whether a principal is allowed to perform an action within your application. To arrive
at the point where an authorization decision is needed, the identity of the principal has already been
established by the authentication process. These concepts are common, and not at all specific to Spring
Security.
At an authentication level, Spring Security supports a wide range of authentication models. Most of
these authentication models are either provided by third parties, or are developed by relevant standards
bodies such as the Internet Engineering Task Force. In addition, Spring Security provides its own set of
authentication features. Specifically, Spring Security currently supports authentication integration with
all of these technologies:
HTTP BASIC authentication headers (an IETF RFC-based standard)
HTTP Digest authentication headers (an IETF RFC-based standard)
HTTP X.509 client certificate exchange (an IETF RFC-based standard)
LDAP (a very common approach to cross-platform authentication needs, especially in large
environments)
Form-based authentication (for simple user interface needs)
OpenID authentication
Authentication based on pre-established request headers (such as Computer Associates Siteminder)
JA-SIG Central Authentication Service (otherwise known as CAS, which is a popular open source
single sign-on system)
Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker
(a Spring remoting protocol)
4.0.2.RELEASE
Spring Security
Automatic "remember-me" authentication (so you can tick a box to avoid re-authentication for a
predetermined period of time)
Anonymous authentication (allowing every unauthenticated call to automatically assume a particular
security identity)
Run-as authentication (which is useful if one call should proceed with a different security identity)
Java Authentication and Authorization Service (JAAS)
JEE container autentication (so you can still use Container Managed Authentication if desired)
Kerberos
Java Open Source Single Sign On (JOSSO) *
OpenNMS Network Management Platform *
AppFuse *
AndroMDA *
Mule ESB *
Direct Web Request (DWR) *
Grails *
Tapestry *
JTrac *
Jasypt *
Roller *
Elastic Path *
Atlassian Crowd *
Your own authentication systems (see below)
(* Denotes provided by a third party
Many independent software vendors (ISVs) adopt Spring Security because of this significant choice of
flexible authentication models. Doing so allows them to quickly integrate their solutions with whatever
their end clients need, without undertaking a lot of engineering or requiring the client to change their
environment. If none of the above authentication mechanisms suit your needs, Spring Security is an
open platform and it is quite simple to write your own authentication mechanism. Many corporate users
of Spring Security need to integrate with "legacy" systems that dont follow any particular security
standards, and Spring Security is happy to "play nicely" with such systems.
Irrespective of the authentication mechanism, Spring Security provides a deep set of authorization
capabilities. There are three main areas of interest - authorizing web requests, authorizing whether
methods can be invoked, and authorizing access to individual domain object instances. To help you
understand the differences, consider the authorization capabilities found in the Servlet Specification web
4.0.2.RELEASE
Spring Security
pattern security, EJB Container Managed Security and file system security respectively. Spring Security
provides deep capabilities in all of these important areas, which well explore later in this reference guide.
1.2 History
Spring Security began in late 2003 as "The Acegi Security System for Spring". A question was posed
on the Spring Developers' mailing list asking whether there had been any consideration given to a
Spring-based security implementation. At the time the Spring community was relatively small (especially
compared with the size today!), and indeed Spring itself had only existed as a SourceForge project from
early 2003. The response to the question was that it was a worthwhile area, although a lack of time
currently prevented its exploration.
With that in mind, a simple security implementation was built and not released. A few weeks later another
member of the Spring community inquired about security, and at the time this code was offered to them.
Several other requests followed, and by January 2004 around twenty people were using the code. These
pioneering users were joined by others who suggested a SourceForge project was in order, which was
duly established in March 2004.
In those early days, the project didnt have any of its own authentication modules. Container Managed
Security was relied upon for the authentication process, with Acegi Security instead focusing on
authorization. This was suitable at first, but as more and more users requested additional container
support, the fundamental limitation of container-specific authentication realm interfaces became clear.
There was also a related issue of adding new JARs to the containers classpath, which was a common
source of end user confusion and misconfiguration.
Acegi Security-specific authentication services were subsequently introduced. Around a year later,
Acegi Security became an official Spring Framework subproject. The 1.0.0 final release was published in
May 2006 - after more than two and a half years of active use in numerous production software projects
and many hundreds of improvements and community contributions.
Acegi Security became an official Spring Portfolio project towards the end of 2007 and was rebranded
as "Spring Security".
Today Spring Security enjoys a strong and active open source community. There are thousands of
messages about Spring Security on the support forums. There is an active core of developers who work
on the code itself and an active community which also regularly share patches and support their peers.
4.0.2.RELEASE
Spring Security
If you are using additional features like LDAP, OpenID, etc. you will need to also include the appropriate
the section called Project Modules.
Maven Repositories
All GA releases (i.e. versions ending in .RELEASE) are deployed to Maven Central, so no additional
Maven repositories need to be declared in your pom.
If you are using a SNAPSHOT version, you will need to ensure you have the Spring Snapshot repository
defined as shown below:
pom.xml.
<repositories>
<!-- ... possibly other repository elements ... -->
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>http://repo.springsource.org/snapshot</url>
</repository>
</repositories>
If you are using a milestone or release candidate version, you will need to ensure you have the Spring
Milestone repository defined as shown below:
pom.xml.
<repositories>
<!-- ... possibly other repository elements ... -->
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>
</repositories>
4.0.2.RELEASE
Spring Security
This will ensure that all the transitive dependencies of Spring Security use the Spring 4.1.6.RELEASE
modules.
Note
This approach uses Mavens "bill of materials" (BOM) concept and is only available in Maven
2.0.9+. For additional details about how dependencies are resolved refer to Mavens Introduction
to the Dependency Mechanism documentation.
Gradle
A minimal Spring Security Gradle set of dependencies typically looks like the following:
build.gradle.
dependencies {
compile 'org.springframework.security:spring-security-web:4.0.2.RELEASE'
compile 'org.springframework.security:spring-security-config:4.0.2.RELEASE'
}
If you are using additional features like LDAP, OpenID, etc. you will need to also include the appropriate
the section called Project Modules.
Gradle Repositories
All GA releases (i.e. versions ending in .RELEASE) are deployed to Maven Central, so using the
mavenCentral() repository is sufficient for GA releases.
build.gradle.
repositories {
mavenCentral()
}
4.0.2.RELEASE
Spring Security
If you are using a SNAPSHOT version, you will need to ensure you have the Spring Snapshot repository
defined as shown below:
build.gradle.
repositories {
maven { url 'https://repo.spring.io/snapshot' }
}
If you are using a milestone or release candidate version, you will need to ensure you have the Spring
Milestone repository defined as shown below:
build.gradle.
repositories {
maven { url 'https://repo.spring.io/milestone' }
}
This will ensure that all the transitive dependencies of Spring Security use the Spring 4.1.6.RELEASE
modules.
Note
This example uses Gradle 1.9, but may need modifications to work in future versions of Gradle
since this is an incubating feature within Gradle.
Project Modules
In Spring Security 3.0, the codebase has been sub-divided into separate jars which more clearly
separate different functionaltiy areas and third-party dependencies. If you are using Maven to build your
project, then these are the modules you will add to your pom.xml. Even if youre not using Maven, wed
recommend that you consult the pom.xml files to get an idea of third-party dependencies and versions.
Alternatively, a good idea is to examine the libraries that are included in the sample applications.
Core - spring-security-core.jar
Contains core authentication and access-contol classes and interfaces, remoting support and basic
provisioning APIs. Required by any application which uses Spring Security. Supports standalone
applications, remote clients, method (service layer) security and JDBC user provisioning. Contains the
top-level packages:
4.0.2.RELEASE
Spring Security
org.springframework.security.core
org.springframework.security.access
org.springframework.security.authentication
org.springframework.security.provisioning
Remoting - spring-security-remoting.jar
Provides intergration with Spring Remoting. You dont need this unless you are writing a remote client
which uses Spring Remoting. The main package is org.springframework.security.remoting.
Web - spring-security-web.jar
Contains filters and related web-security infrastructure code. Anything with a servlet API dependency.
Youll need it if you require Spring Security web authentication services and URL-based access-control.
The main package is org.springframework.security.web.
Config - spring-security-config.jar
Contains the security namespace parsing code. You need it if you are using the Spring Security XML
namespace for configuration. The main package is org.springframework.security.config.
None of the classes are intended for direct use in an application.
LDAP - spring-security-ldap.jar
LDAP authentication and provisioning code. Required if you need to use LDAP authentication or manage
LDAP user entries. The top-level package is org.springframework.security.ldap.
ACL - spring-security-acl.jar
Specialized
domain
object
ACL
implementation.
Used
to
specific domain object instances within your application. The
org.springframework.security.acls.
apply
security
top-level package
to
is
CAS - spring-security-cas.jar
Spring Securitys CAS client integration. If you want to use Spring Security web authentication with a
CAS single sign-on server. The top-level package is org.springframework.security.cas.
OpenID - spring-security-openid.jar
OpenID web authentication support. Used to authenticate users against an external OpenID server.
org.springframework.security.openid. Requires OpenID4Java.
4.0.2.RELEASE
Spring Security
10
This will give you access to the entire project history (including all releases and branches) on your local
machine.
4.0.2.RELEASE
Spring Security
11
2.1 Features
Below are the highlights of the new features found in Spring Security 4.0.
Web Socket Support
Test Support
Spring Data Integration
CSRF Token Argument Resolver
More Secure Defaults
Methods with role in them do not require ROLE_ For example, previously the following would be
required within XML configuration:
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
Now you can optionally omit the ROLE_ prefix. We do this to remove duplication. Specifically, since
the expression hasRole already defines the value as a role it automatically adds the prefix if it is not
there. For example, the following is the same as the previous configuration:
<intercept-url pattern="/**" access="hasRole('USER')"/>
4.0.2.RELEASE
Spring Security
12
4.0.2.RELEASE
Spring Security
13
3. Java Configuration
General support for Java Configuration was added to Spring framework in Spring 3.1. Since Spring
Security 3.2 there has been Spring Security Java Configuration support which enables users to easily
configure Spring Security without the use of any XML.
If you are familiar with the Chapter 4, Security Namespace Configuration then you should find quite a
few similarities between it and the Security Java Configuration support.
Note
Spring Security provides lots of sample applications that end in -jc which demonstrate the use
of Spring Security Java Configuration.
Note
The name of the configureGlobal method is not important. However, it is important to only
configure AuthenticationManagerBuilder in a class annotated with either @EnableWebSecurity,
@EnableGlobalMethodSecurity, or @EnableGlobalAuthentication. Doing otherwise
has unpredictable results.
There really isnt much to this configuration, but it does a lot. You can find a summary of the features
below:
Require authentication to every URL in your application
Generate a login form for you
Allow the user with the Username user and the Password password to authenticate with form based
authentication
Allow the user to logout
4.0.2.RELEASE
Spring Security
14
AbstractSecurityWebApplicationInitializer
The next step is to register the springSecurityFilterChain with the war.
This can be done in Java Configuration with Springs WebApplicationInitializer
support in a Servlet 3.0+ environment. Not suprisingly, Spring Security provides
a base class AbstractSecurityWebApplicationInitializer that will ensure the
springSecurityFilterChain gets registered for you. The way in which we use
AbstractSecurityWebApplicationInitializer differs depending on if we are already using
Spring or if Spring Security is the only Spring component in our application.
the section called AbstractSecurityWebApplicationInitializer without Existing Spring - Use these
instructions if you are not using Spring already
the section called AbstractSecurityWebApplicationInitializer with Spring MVC - Use these
instructions if you are already using Spring
4.0.2.RELEASE
Spring Security
15
This would simply only register the springSecurityFilterChain Filter for every URL in your application.
After that we would ensure that SecurityConfig was loaded in our existing ApplicationInitializer. For
example, if we were using Spring MVC it would be added in the getRootConfigClasses()
public class MvcWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class };
}
// ... other overrides ...
}
3.2 HttpSecurity
Thus far our SecurityConfig only contains information about how to authenticate our users.
How does Spring Security know that we want to require all users to be authenticated? How
does Spring Security know we want to support form based authentication? The reason for
this is that the WebSecurityConfigurerAdapter provides a default configuration in the
configure(HttpSecurity http) method that looks like:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
4.0.2.RELEASE
Spring Security
16
The Java Configuration equivalent of closing an XML tag is expressed using the and() method which
allows us to continue configuring the parent. If you read the code it also makes sense. I want to configure
authorized requests and configure form login and configure HTTP Basic authentication.
However, Java configuration has different defaults URLs and parameters. Keep this in mind when
creating custom login pages. The result is that our URLs are more RESTful. Additionally, it is not quite
so obvious we are using Spring Security which helps to prevent information leaks. For example:
We must grant all users (i.e. unauthenticated users) access to our log in page. The
formLogin().permitAll() method allows granting access to all users for all URLs associated
with form based log in.
An example log in page implemented with JSPs for our current configuration can be seen below:
Note
The login page below represents our current configuration. We could easily update our
configuration if some of the defaults do not meet our needs.
4.0.2.RELEASE
Spring Security
17
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
<button type="submit" class="btn">Log in</button>
</form>
If the query parameter error exists, authentication was attempted and failed
If the query parameter logout exists, the user was successfully logged out
We must the section called Include the CSRF Token To learn more read the Chapter 16, Cross
Site Request Forgery (CSRF) section of the reference
.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
// ...
.formLogin();
}
4.0.2.RELEASE
Spring Security
18
Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
You will notice that since we are using the hasRole expression we do not need to specify the
"ROLE_" prefix.
Any URL that has not already been matched on only requires that the user be authenticated
.logout()
.logoutUrl("/my/logout")
.logoutSuccessUrl("/my/index")
.logoutSuccessHandler(logoutSuccessHandler)
.invalidateHttpSession(true)
.addLogoutHandler(logoutHandler)
.deleteCookies(cookieNamesToClear)
.and()
...
Provides
logout
support.
This
is
automatically
applied
when
using
WebSecurityConfigurerAdapter.
The URL that triggers log out to occur (default is /logout). If CSRF protection is enabled (default),
then the request must also be a POST. For for information, please consult the JavaDoc.
The URL to redirect to after logout has occurred. The default is /login?logout. For for
information, please consult the JavaDoc.
Lets you specify a custom LogoutSuccessHandler. If this is specified, logoutSuccessUrl()
is ignored. For for information, please consult the JavaDoc.
Specify whether to invalidate the HttpSession at the time of logout. This is true by default.
Configures the SecurityContextLogoutHandler under the covers. For for information, please
consult the JavaDoc.
Adds a LogoutHandler. SecurityContextLogoutHandler is added as the last
LogoutHandler by default.
Allows specifying the names of cookies to be removed on logout success. This is a shortcut for
adding a CookieClearingLogoutHandler explicitly.
Note
Logouts can of course also be configured using the XML Namespace notation. Please see the
documentation for the logout element in the Spring Security XML Namespace section for further
details.
4.0.2.RELEASE
Spring Security
19
Generally, in order to customize logout functionality, you can add LogoutHandler and/or
LogoutSuccessHandler implementations. For many common scenarios, these handlers are applied
under the covers when using the fluent API.
LogoutHandler
Generally, LogoutHandler implementations indicate classes that are able to participate in logout
handling. They are expected to be invoked to perform necessary cleanup. As such they should not throw
exceptions. Various implementations are provided:
PersistentTokenBasedRememberMeServices
TokenBasedRememberMeServices
CookieClearingLogoutHandler
CsrfLogoutHandler
SecurityContextLogoutHandler
Please see Section 15.4, Remember-Me Interfaces and Implementations for details.
Instead of providing LogoutHandler implementations directly, the fluent API also provides
shortcuts that provide the respective LogoutHandler implementations under the covers. E.g.
deleteCookies() allows specifying the names of one or more cookies to be removed on logout
success. This is a shortcut compared to adding a CookieClearingLogoutHandler.
LogoutSuccessHandler
The LogoutSuccessHandler is called after a successful logout by the LogoutFilter, to handle
e.g. redirection or forwarding to the appropriate destination. Note that the interface is almost the same
as the LogoutHandler but may raise an exception.
The following implementations are provided:
SimpleUrlLogoutSuccessHandler
HttpStatusReturningLogoutSuccessHandler
As mentioned above, you dont need to specify the SimpleUrlLogoutSuccessHandler directly.
Instead, the fluent API provides a shortcut by setting the logoutSuccessUrl(). This will setup the
SimpleUrlLogoutSuccessHandler under the covers. The provided URL will be redirected to after
a logout has occurred. The default is /login?logout.
The HttpStatusReturningLogoutSuccessHandler can be interesting in REST API type
scenarios. Instead of redirecting to a URL upon the successful logout, this LogoutSuccessHandler
allows you to provide a plain HTTP status code to be returned. If not configured a status code 200 will
be returned by default.
4.0.2.RELEASE
Spring Security
20
3.6 Authentication
Thus far we have only taken a look at the most basic authentication configuration. Lets take a look at
a few slightly more advanced options for configuring authentication.
In Memory Authentication
We have already seen an example of configuring in memory authentication for a single user. Below is
an example to configure multiple users:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
JDBC Authentication
You can find the updates to suppport JDBC based authentication. The example below assumes that you
have already defined a DataSource within your application. The jdbc-jc sample provides a complete
example of using JDBC based authentication.
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withDefaultSchema()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
LDAP Authentication
You can find the updates to suppport LDAP based authentication. The ldap-jc sample provides a
complete example of using LDAP based authentication.
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups");
}
4.0.2.RELEASE
Spring Security
21
The example above uses the following LDIF and an embedded Apache DS LDAP instance.
users.ldif.
dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people
dn: uid=admin,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rod Johnson
sn: Johnson
uid: admin
userPassword: password
dn: uid=user,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Dianne Emu
sn: Emu
uid: user
userPassword: password
dn: cn=user,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: user
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
uniqueMember: uid=user,ou=people,dc=springframework,dc=org
dn: cn=admin,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: admin
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
4.0.2.RELEASE
Spring Security
22
@EnableWebSecurity
public class MultiHttpSecurityConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
@Configuration
@Order(1)
}
}
@Configuration
EnableGlobalMethodSecurity
We can enable annotation-based security using the @EnableGlobalMethodSecurity annotation on
any @Configuration instance. For example, the following would enable Spring Securitys @Secured
annotation.
4.0.2.RELEASE
Spring Security
23
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Adding an annotation to a method (on an class or interface) would then limit the access to that method
accordingly. Spring Securitys native annotation support defines a set of attributes for the method. These
will be passed to the AccessDecisionManager for it to make the actual decision:
public interface BankService {
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account readAccount(Long id);
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account[] findAccounts();
@Secured("ROLE_TELLER")
public Account post(Account account, double amount);
}
These are standards-based and allow simple role-based constraints to be applied but do not have the
power Spring Securitys native annotations. To use the new expression-based syntax, you would use
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
// ...
}
GlobalMethodSecurityConfiguration
Sometimes you may need to perform operations that are more complicated than are possible with
the @EnableGlobalMethodSecurity annotation allow. For these instances, you can extend the
GlobalMethodSecurityConfiguration ensuring that the @EnableGlobalMethodSecurity
annotation is present on your subclass. For example, if you wanted to provide a custom
MethodSecurityExpressionHander, you could use the following configuration:
4.0.2.RELEASE
Spring Security
24
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
// ... create and return custom MethodSecurityExpressionHandler ...
return expressionHander;
}
}
can
be
overriden,
refer
to
the
4.0.2.RELEASE
Spring Security
25
This is much simpler than wiring up the equivalent Apache Directory Server beans. The most common
alternative configuration requirements are supported by attributes on the ldap-server element and
the user is isolated from worrying about which beans they need to create and what the bean property
2
names are. . Use of a good XML editor while editing the application context file should provide
information on the attributes and elements that are available. We would recommend that you try out the
SpringSource Tool Suite as it has special features for working with standard Spring namespaces.
To start using the security namespace in your application context, you need to have the springsecurity-config jar on your classpath. Then all you need to do is add the schema declaration to
your application context file:
<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.xsd">
...
</beans>
In many of the examples you will see (and in the sample) applications, we will often use "security" as
the default namespace rather than "beans", which means we can omit the prefix on all the security
namespace elements, making the content easier to read. You may also want to do this if you have your
application context divided up into separate files and have most of your security configuration in one of
them. Your security application context file would then start like this
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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.xsd">
...
</beans:beans>
Well assume this syntax is being used from now on in this chapter.
2
You can find out more about the use of the ldap-server element in the chapter on Chapter 26, LDAP Authentication.
4.0.2.RELEASE
Spring Security
26
web.xml Configuration
The first thing you need to do is add the following filter declaration to your web.xml file:
<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>
This provides a hook into the Spring Security web infrastructure. DelegatingFilterProxy is a Spring
Framework class which delegates to a filter implementation which is defined as a Spring bean in your
application context. In this case, the bean is named "springSecurityFilterChain", which is an internal
infrastructure bean created by the namespace to handle web security. Note that you should not use
this bean name yourself. Once youve added this to your web.xml, youre ready to start editing your
application context file. Web security services are configured using the <http> element.
4.0.2.RELEASE
Spring Security
27
Which says that we want all URLs within our application to be secured, requiring the role ROLE_USER
to access them, we want to log in to the application using a form with username and password, and
that we want a logout URL registered which will allow us to log out of the application. <http> element
is the parent for all web-related namespace functionality. The <intercept-url> element defines a
4
pattern which is matched against the URLs of incoming requests using an ant path style syntax .
You can also use regular-expression matching as an alternative (see the namespace appendix for more
details). The access attribute defines the access requirements for requests matching the given pattern.
With the default configuration, this is typically a comma-separated list of roles, one of which a user
must have to be allowed to make the request. The prefix"ROLE_" is a marker which indicates that a
simple comparison with the users authorities should be made. In other words, a normal role-based
check should be used. Access-control in Spring Security is not limited to the use of simple roles (hence
the use of the prefix to differentiate between different types of security attributes). Well see later how
the interpretation can vary footnote:[The interpretation of the comma-separated values in the access
attribute depends on the implementation of the #1# which is used. In Spring Security 3.0, the attribute
can also be populated with an #2#.
Note
You can use multiple <intercept-url> elements to define different access requirements for
different sets of URLs, but they will be evaluated in the order listed and the first match will be
used. So you must put the most specific matches at the top. You can also add a method attribute
to limit the match to a particular HTTP method (GET, POST, PUT etc.).
To add some users, you can define a set of test data directly in the namespace:
<authentication-manager>
<authentication-provider>
<user-service>
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
If you are familiar with pre-namespace versions of the framework, you can probably already
guess roughly whats going on here. The <http> element is responsible for creating a
FilterChainProxy and the filter beans which it uses. Common problems like incorrect filter
ordering are no longer an issue as the filter positions are predefined.
The <authentication-provider> element creates a DaoAuthenticationProvider bean
and the <user-service> element creates an InMemoryDaoImpl. All authentication4
See the section on Section 11.4, Request Matching and HttpFirewall in the Web Application Infrastructure chapter for more
details on how matches are actually performed.
4.0.2.RELEASE
Spring Security
28
Also note that weve added an extra intercept-url element to say that any requests for the login
5
page should be available to anonymous users and also the AuthenticatedVoter class for more details
on how the value IS_AUTHENTICATED_ANONYMOUSLY is processed.]. Otherwise the request would be
matched by the pattern /** and it wouldnt be possible to access the login page itself! This is a common
configuration error and will result in an infinite loop in the application. Spring Security will emit a warning
in the log if your login page appears to be secured. It is also possible to have all requests matching a
particular pattern bypass the security filter chain completely, by defining a separate http element for
the pattern like this:
<http pattern="/css/**" security="none"/>
<http pattern="/login.jsp*" security="none"/>
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page='/login.jsp'/>
</http>
From Spring Security 3.1 it is now possible to use multiple http elements to define separate security
filter chain configurations for different request patterns. If the pattern attribute is omitted from an http
element, it matches all requests. Creating an unsecured pattern is a simple example of this syntax,
5
4.0.2.RELEASE
Spring Security
29
where the pattern is mapped to an empty filter chain . Well look at this new syntax in more detail in
the chapter on the Security Filter Chain.
Its important to realise that these unsecured requests will be completely oblivious to any Spring
Security web-related configuration or additional attributes such as requires-channel, so you will
not be able to access information on the current user or call secured methods during the request. Use
access='IS_AUTHENTICATED_ANONYMOUSLY' as an alternative if you still want the security filter
chain to be applied.
If you want to use basic authentication instead of form login, then change the configuration to
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
<http-basic />
</http>
Basic authentication will then take precedence and will be used to prompt for a login when a user
attempts to access a protected resource. Form login is still available in this configuration if you wish to
use it, for example through a login form embedded in another web page.
Setting a Default Post-Login Destination
If a form login isnt prompted by an attempt to access a protected resource, the default-targeturl option comes into play. This is the URL the user will be taken to after successfully logging in, and
defaults to "/". You can also configure things so that the user always ends up at this page (regardless
of whether the login was "on-demand" or they explicitly chose to log in) by setting the always-usedefault-target attribute to "true". This is useful if your application always requires that the user
starts at a "home" page, for example:
<http pattern="/login.htm*" security="none"/>
<http use-expressions="false">
<intercept-url pattern='/**' access='ROLE_USER' />
<form-login login-page='/login.htm' default-target-url='/home.htm'
always-use-default-target='true' />
</http>
For even more control over the destination, you can use the authentication-success-handlerref attribute as an alternative to default-target-url. The referenced bean should be an instance
of AuthenticationSuccessHandler. Youll find more on this in the Core Filters chapter and also in
the namespace appendix, as well as information on how to customize the flow when authentication fails.
Logout Handling
The logout element adds support for logging out by navigating to a particular URL. The default logout
URL is /logout, but you can set it to something else using the logout-url attribute. More information
on other available attributes may be found in the namespace appendix.
The use of multiple <http> elements is an important feature, allowing the namespace to simultaneously support both stateful
and stateless paths within the same application, for example. The previous syntax, using the attribute filters="none" on an
intercept-url element is incompatible with this change and is no longer supported in 3.1.
4.0.2.RELEASE
Spring Security
30
database or an LDAP server. LDAP namespace configuration is dealt with in the LDAP chapter, so we
wont cover it here. If you have a custom implementation of Spring Securitys UserDetailsService,
called "myUserDetailsService" in your application context, then you can authenticate against this using
<authentication-manager>
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
Where "securityDataSource" is the name of a DataSource bean in the application context, pointing at
a database containing the standard Spring Security user data tables. Alternatively, you could configure
a Spring Security JdbcDaoImpl bean and point at that using the user-service-ref attribute:
<authentication-manager>
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
4.0.2.RELEASE
Spring Security
31
Bcrypt is a good choice for most cases, unless you have a legacy system which forces you to use
a different algorithm. If you are using a simple hashing algorithm or, even worse, storing plain text
passwords, then you should consider migrating to a more secure option like bcrypt.
With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern
7
using HTTP, they will first be redirected to an HTTPS URL . The available options are "http", "https" or
"any". Using the value "any" means that either HTTP or HTTPS can be used.
If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port
mappings as follows:
<http>
...
<port-mappings>
<port-mapping http="9080" https="9443"/>
</port-mappings>
</http>
Note that in order to be truly secure, an application should not use HTTP at all or switch between
HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and use a secure
connection throughout to avoid any possibility of man-in-the-middle attacks.
Session Management
Detecting Timeouts
You can configure Spring Security to detect the submission of an invalid session ID and redirect the
user to an appropriate URL. This is achieved through the session-management element:
<http>
...
<session-management invalid-session-url="/invalidSession.htm" />
</http>
Note that if you use this mechanism to detect session timeouts, it may falsely report an error if the
user logs out and then logs back in without closing the browser. This is because the session cookie is
7
For more details on how channel-processing is implemented, see the Javadoc for ChannelProcessingFilter and related
classes.
4.0.2.RELEASE
Spring Security
32
not cleared when you invalidate the session and will be resubmitted even if the user has logged out.
You may be able to explicitly delete the JSESSIONID cookie on logging out, for example by using the
following syntax in the logout handler:
<http>
<logout delete-cookies="JSESSIONID" />
</http>
Unfortunately this cant be guaranteed to work with every servlet container, so you will need to test it
in your environment
Note
If you are running your application behind a proxy, you may also be able to remove the session
cookie by configuring the proxy server. For example, using Apache HTTPDs mod_headers, the
following directive would delete the JSESSIONID cookie by expiring it in the response to a logout
request (assuming the application is deployed under the path /tutorial):
<LocationMatch "/tutorial/logout">
Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
</LocationMatch>
This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated.
Often you would prefer to prevent a second login, in which case you can use
<http>
...
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>
The second login will then be rejected. By "rejected", we mean that the user will be sent to the
authentication-failure-url if form-based login is being used. If the second authentication takes
place through another non-interactive mechanism, such as "remember-me", an "unauthorized" (401)
error will be sent to the client. If instead you want to use an error page, you can add the attribute
session-authentication-error-url to the session-management element.
4.0.2.RELEASE
Spring Security
33
If you are using a customized authentication filter for form-based login, then you have to configure
concurrent session control support explicitly. More details can be found in the Session Management
chapter.
Session Fixation Attack Protection
Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a
session by accessing a site, then persuade another user to log in with the same session (by sending
them a link containing the session identifier as a parameter, for example). Spring Security protects
against this automatically by creating a new session or otherwise changing the session ID when a user
logs in. If you dont require this protection, or it conflicts with some other requirement, you can control the
behavior using the session-fixation-protection attribute on <session-management>, which
has four options
none - Dont do anything. The original session will be retained.
newSession - Create a new "clean" session, without copying the existing session data (Spring
Security-related attributes will still be copied).
migrateSession - Create a new session and copy all existing session attributes to the new session.
This is the default in Servlet 3.0 or older containers.
changeSessionId - Do not create a new session. Instead, use the session fixation protection
provided by the Servlet container (HttpServletRequest#changeSessionId()). This option is
only available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in older containers will
result in an exception. This is the default in Servlet 3.1 and newer containers.
When session fixation protection occurs, it results in a SessionFixationProtectionEvent being
published in the application context. If you use changeSessionId, this protection will also result in
any javax.servlet.http.HttpSessionIdListener s being notified, so use caution if your code
listens for both events. See the Session Management chapter for additional information.
OpenID Support
The namespace supports OpenID login either instead of, or in addition to normal form-based login, with
a simple change:
<http>
<intercept-url pattern="/**" access="ROLE_USER" />
<openid-login />
</http>
You should then register yourself with an OpenID provider (such as myopenid.com), and add the user
information to your in-memory <user-service> :
<user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
You should be able to login using the myopenid.com site to authenticate. It is also possible to select a
specific UserDetailsService bean for use OpenID by setting the user-service-ref attribute on
the openid-login element. See the previous section on authentication providers for more information.
Note that we have omitted the password attribute from the above user configuration, since this set of
user data is only being used to load the authorities for the user. A random password will be generate
internally, preventing you from accidentally using this user data as an authentication source elsewhere
in your configuration.
4.0.2.RELEASE
Spring Security
34
Attribute Exchange
Support for OpenID attribute exchange. As an example, the following configuration would attempt to
retrieve the email and full name from the OpenID provider, for use by the application:
<openid-login>
<attribute-exchange>
<openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
<openid-attribute name="name" type="http://axschema.org/namePerson"/>
</attribute-exchange>
</openid-login>
The "type" of each OpenID attribute is a URI, determined by a particular schema, in this case http://
axschema.org/. If an attribute must be retrieved for successful authentication, the required attribute
can be set. The exact schema and attributes supported will depend on your OpenID provider. The
attribute values are returned as part of the authentication process and can be accessed afterwards
using the following code:
OpenIDAuthenticationToken token =
(OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
List<OpenIDAttribute> attributes = token.getAttributes();
The OpenIDAttribute contains the attribute type and the retrieved value (or values in the case
of multi-valued attributes). Well see more about how the SecurityContextHolder class is used
when we look at core Spring Security components in the technical overview chapter. Multiple attribute
exchange configurations are also be supported, if you wish to use multiple identity providers. You can
supply multiple attribute-exchange elements, using an identifier-matcher attribute on each.
This contains a regular expression which will be matched against the OpenID identifier supplied by
the user. See the OpenID sample application in the codebase for an example configuration, providing
different attribute lists for the Google, Yahoo and MyOpenID providers.
Response Headers
For additional information on how to customize the headers element refer to the Chapter 17, Security
HTTP Response Headers section of the reference.
4.0.2.RELEASE
Spring Security
35
metadata level, before the classes have been instantiated. This has implications for how you add
your own filters to the stack as the entire filter list must be known during the parsing of the <http>
element, so the syntax has changed slightly in 3.0.
The filters, aliases and namespace elements/attributes which create the filters are shown in Table 4.1,
Standard Filter Aliases and Ordering. The filters are listed in the order in which they occur in the filter
chain.
Table 4.1. Standard Filter Aliases and Ordering
Alias
Filter Class
Namespace Element or
Attribute
CHANNEL_FILTER
ChannelProcessingFilter
http/intercepturl@requires-channel
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter
http
CONCURRENT_SESSION_FILTER
ConcurrentSessionFilter
session-management/
concurrency-control
HEADERS_FILTER
HeaderWriterFilter
http/headers
CSRF_FILTER
CsrfFilter
http/csrf
LOGOUT_FILTER
LogoutFilter
http/logout
X509_FILTER
X509AuthenticationFilter http/x509
PRE_AUTH_FILTER
AbstractPreAuthenticatedProcessingFilter
N/A
Subclasses
CAS_FILTER
CasAuthenticationFilter
FORM_LOGIN_FILTER
UsernamePasswordAuthenticationFilter
http/form-login
BASIC_AUTH_FILTER
BasicAuthenticationFilterhttp/http-basic
N/A
SERVLET_API_SUPPORT_FILTER
SecurityContextHolderAwareRequestFilter
http/@servlet-apiprovision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http/@jaas-apiprovision
REMEMBER_ME_FILTER
RememberMeAuthenticationFilter
http/remember-me
ANONYMOUS_FILTER
AnonymousAuthenticationFilter
http/anonymous
SESSION_MANAGEMENT_FILTER
SessionManagementFilter
session-management
EXCEPTION_TRANSLATION_FILTER
ExceptionTranslationFilter
http
FILTER_SECURITY_INTERCEPTOR
FilterSecurityInterceptorhttp
SWITCH_USER_FILTER
SwitchUserFilter
N/A
You can add your own filter to the stack, using the custom-filter element and one of these names
to specify the position your filter should appear at:
4.0.2.RELEASE
Spring Security
36
<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
You can also use the after or before attributes if you want your filter to be inserted before or after
another filter in the stack. The names "FIRST" and "LAST" can be used with the position attribute to
indicate that you want your filter to appear before or after the entire stack, respectively.
Avoiding filter position conflicts
If you are inserting a custom filter which may occupy the same position as one of the standard
filters created by the namespace then its important that you dont include the namespace versions
by mistake. Remove any elements which create filters whose functionality you want to replace.
Note that you cant replace filters which are created by the use of the <http>
element itself - SecurityContextPersistenceFilter, ExceptionTranslationFilter
or FilterSecurityInterceptor. Some other filters are added by default, but you can
disable them. An AnonymousAuthenticationFilter is added by default and unless you have
session-fixation protection disabled, a SessionManagementFilter will also be added to the
filter chain.
If youre replacing a namespace filter which requires an authentication entry point (i.e. where the
authentication process is triggered by an attempt by an unauthenticated user to access to a secured
resource), you will need to add a custom entry point bean too.
Setting a Custom AuthenticationEntryPoint
If you arent using form login, OpenID or basic authentication through the namespace, you may want
to define an authentication filter and entry point using a traditional bean syntax and link them into the
namespace, as weve just seen. The corresponding AuthenticationEntryPoint can be set using
the entry-point-ref attribute on the <http> element.
The CAS sample application is a good example of the use of custom beans with the namespace,
including this syntax. If you arent familiar with authentication entry points, they are discussed in the
technical overview chapter.
4.0.2.RELEASE
Spring Security
37
Adding an annotation to a method (on an class or interface) would then limit the access to that method
accordingly. Spring Securitys native annotation support defines a set of attributes for the method. These
will be passed to the AccessDecisionManager for it to make the actual decision:
public interface BankService {
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account readAccount(Long id);
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account[] findAccounts();
@Secured("ROLE_TELLER")
public Account post(Account account, double amount);
}
These are standards-based and allow simple role-based constraints to be applied but do not have the
power Spring Securitys native annotations. To use the new expression-based syntax, you would use
<global-method-security pre-post-annotations="enabled" />
Expression-based annotations are a good choice if you need to define simple rules that go beyond
checking the role names against the users list of authorities.
Note
The annotated methods will only be secured for instances which are defined as Spring beans (in
the same application context in which method-security is enabled). If you want to secure instances
which are not created by Spring (using the new operator, for example) then you need to use
AspectJ.
Note
You can enable more than one type of annotation in the same application, but only one type
should be used for any interface or class as the behaviour will not be well-defined otherwise. If two
annotations are found which apply to a particular method, then only one of them will be applied.
4.0.2.RELEASE
Spring Security
38
This will protect all methods on beans declared in the application context whose classes are in the
com.mycompany package and whose class names end in "Service". Only users with the ROLE_USER
role will be able to invoke these methods. As with URL matching, the most specific matches must come
first in the list of pointcuts, as the first matching expression will be used. Security annotations take
precedence over pointcuts.
The syntax for web security is the same, but on the http element:
<http access-decision-manager-ref="myAccessDecisionManagerBean">
...
</http>
4.0.2.RELEASE
Spring Security
39
manager namespace element. You cant use a custom AuthenticationManager if you are using
either HTTP or method security through the namespace, but this should not be a problem as you have
full control over the AuthenticationProvider s that are used.
You may want to register additional AuthenticationProvider beans with the ProviderManager
and you can do this using the <authentication-provider> element with the ref attribute, where
the value of the attribute is the name of the provider bean you want to add. For example:
<authentication-manager>
<authentication-provider ref="casAuthenticationProvider"/>
</authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
</bean>
Another common requirement is that another bean in the context may require a reference to the
AuthenticationManager. You can easily register an alias for the AuthenticationManager and
use this name elsewhere in your application context.
<security:authentication-manager alias="authenticationManager">
...
</security:authentication-manager>
<bean id="customizedFormLoginFilter"
class="com.somecompany.security.web.CustomFormLoginFilter">
<property name="authenticationManager" ref="authenticationManager"/>
...
</bean>
4.0.2.RELEASE
Spring Security
40
5. Sample Applications
There are several sample web applications that are available with the project. To avoid an overly large
download, only the "tutorial" and "contacts" samples are included in the distribution zip file. The others
can be built directly from the source which you can obtain as described in the introduction. Its easy to
build the project yourself and theres more information on the project web site at http://spring.io/springsecurity/. All paths referred to in this chapter are relative to the project source directory.
5.2 Contacts
The Contacts Sample is an advanced example in that it illustrates the more powerful features of domain
object access control lists (ACLs) in addition to basic application security. The application provides an
interface with which the users are able to administer a simple database of contacts (the domain objects).
To deploy, simply copy the WAR file from Spring Security distribution into your containers webapps
directory. The war should be called spring-security-samples-contacts-3.1.x.war (the
appended version number will vary depending on what release you are using).
After starting your container, check the application can load. Visit http://localhost:8080/contacts (or
whichever URL is appropriate for your web container and the WAR you deployed).
Next, click "Debug". You will be prompted to authenticate, and a series of usernames and passwords
are suggested on that page. Simply authenticate with any of these and view the resulting page. It should
contain a success message similar to the following:
4.0.2.RELEASE
Spring Security
41
Once you successfully receive the above message, return to the sample applications home page and
click "Manage". You can then try out the application. Notice that only the contacts available to the
currently logged on user are displayed, and only users with ROLE_SUPERVISOR are granted access to
delete their contacts. Behind the scenes, the MethodSecurityInterceptor is securing the business
objects.
The application allows you to modify the access control lists associated with different contacts. Be sure
to give this a try and understand how it works by reviewing the application context XML files.
4.0.2.RELEASE
Spring Security
42
4.0.2.RELEASE
Spring Security
43
4.0.2.RELEASE
Spring Security
44
7. Technical Overview
7.1 Runtime Environment
Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring Security aims to
operate in a self-contained manner, there is no need to place any special configuration files into your
Java Runtime Environment. In particular, there is no need to configure a special Java Authentication
and Authorization Service (JAAS) policy file or place Spring Security into common classpath locations.
Similarly, if you are using an EJB Container or Servlet Container there is no need to put any special
configuration files anywhere, nor include Spring Security in a server classloader. All the required files
will be contained within your application.
This design offers maximum deployment time flexibility, as you can simply copy your target artifact (be
it a JAR, WAR or EAR) from one system to another and it will immediately work.
4.0.2.RELEASE
Spring Security
46
normally need to create an Authentication object yourself, but it is fairly common for users to query
the Authentication object. You can use the following code block - from anywhere in your application
- to obtain the name of the currently authenticated user, for example:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
The object returned by the call to getContext() is an instance of the SecurityContext interface.
This is the object that is kept in thread-local storage. As well see below, most authentication
mechanisms withing Spring Security return an instance of UserDetails as the principal.
The UserDetailsService
Another item to note from the above code fragment is that you can obtain a principal from the
Authentication object. The principal is just an Object. Most of the time this can be cast into a
UserDetails object. UserDetails is a core interface in Spring Security. It represents a principal,
but in an extensible and application-specific way. Think of UserDetails as the adapter between
your own user database and what Spring Security needs inside the SecurityContextHolder.
Being a representation of something from your own user database, quite often you will cast the
UserDetails to the original object that your application provided, so you can call business-specific
methods (like`getEmail(), `getEmployeeNumber() and so on).
By now youre probably wondering, so when do I provide a UserDetails object? How do I do that? I
thought you said this thing was declarative and I didnt need to write any Java code - what gives? The
short answer is that there is a special interface called UserDetailsService. The only method on this
interface accepts a String-based username argument and returns a UserDetails:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
This is the most common approach to loading information for a user within Spring Security and you will
see it used throughout the framework whenever information on a user is required.
On successful authentication, UserDetails is used to build the Authentication object that is
stored in the SecurityContextHolder (more on this below). The good news is that we provide
a number of UserDetailsService implementations, including one that uses an in-memory map
(InMemoryDaoImpl) and another that uses JDBC (JdbcDaoImpl). Most users tend to write their
own, though, with their implementations often simply sitting on top of an existing Data Access Object
(DAO) that represents their employees, customers, or other users of the application. Remember
the advantage that whatever your UserDetailsService returns can always be obtained from the
SecurityContextHolder using the above code fragment.
Note
There is often some confusion about UserDetailsService. It is purely a DAO for user
data and performs no other function other than to supply that data to other components
within the framework. In particular, it does not authenticate the user, which is done
by the AuthenticationManager. In many cases it makes more sense to implement
AuthenticationProvider directly if you require a custom authentication process.
4.0.2.RELEASE
Spring Security
47
GrantedAuthority
Besides the principal, another important method provided by Authentication is
getAuthorities(). This method provides an array of GrantedAuthority objects. A
GrantedAuthority is, not surprisingly, an authority that is granted to the principal. Such authorities
are usually "roles", such as ROLE_ADMINISTRATOR or ROLE_HR_SUPERVISOR. These roles are later
on configured for web authorization, method authorization and domain object authorization. Other
parts of Spring Security are capable of interpreting these authorities, and expect them to be present.
GrantedAuthority objects are usually loaded by the UserDetailsService.
Usually the GrantedAuthority objects are application-wide permissions. They are not specific to a
given domain object. Thus, you wouldnt likely have a GrantedAuthority to represent a permission
to Employee object number 54, because if there are thousands of such authorities you would quickly
run out of memory (or, at the very least, cause the application to take a long time to authenticate a user).
Of course, Spring Security is expressly designed to handle this common requirement, but youd instead
use the projects domain object security capabilities for this purpose.
Summary
Just to recap, the major building blocks of Spring Security that weve seen so far are:
SecurityContextHolder, to provide access to the SecurityContext.
SecurityContext, to hold the Authentication and possibly request-specific security
information.
Authentication, to represent the principal in a Spring Security-specific manner.
GrantedAuthority, to reflect the application-wide permissions granted to a principal.
UserDetails, to provide the necessary information to build an Authentication object from your
applications DAOs or other source of security data.
UserDetailsService, to create a UserDetails when passed in a String-based username (or
certificate ID or the like).
Now that youve gained an understanding of these repeatedly-used components, lets take a closer look
at the process of authentication.
7.3 Authentication
Spring Security can participate in many different authentication environments. While we recommend
people use Spring Security for authentication and not integrate with existing Container Managed
Authentication, it is nevertheless supported - as is integrating with your own proprietary authentication
system.
4.0.2.RELEASE
Spring Security
48
3. The context information for that user is obtained (their list of roles and so on).
4. A security context is established for the user
5. The user proceeds, potentially to perform some operation which is potentially protected by an access
control mechanism which checks the required permissions for the operation against the current
security context information.
The first three items constitute the authentication process so well take a look at how these take place
within Spring Security.
1. The username and password are obtained and combined into an instance of
UsernamePasswordAuthenticationToken (an instance of the Authentication interface,
which we saw earlier).
2. The token is passed to an instance of AuthenticationManager for validation.
3. The AuthenticationManager returns a fully populated Authentication instance on successful
authentication.
4. The
security
context
is
established
by
calling
SecurityContextHolder.getContext().setAuthentication(), passing in the returned
authentication object.
From that point on, the user is considered to be authenticated. Lets look at some code as an example.
4.0.2.RELEASE
Spring Security
49
import
import
import
import
org.springframework.security.authentication.*;
org.springframework.security.core.*;
org.springframework.security.core.authority.SimpleGrantedAuthority;
org.springframework.security.core.context.SecurityContextHolder;
Here we have written a little program that asks the user to enter a username and password and performs
the above sequence. The AuthenticationManager which weve implemented here will authenticate
any user whose username and password are the same. It assigns a single role to every user. The output
from the above will be something like:
Please enter your username:
bob
Please enter your password:
password
Authentication failed: Bad Credentials
Please enter your username:
bob
Please enter your password:
bob
Successfully authenticated. Security context contains: \
org.springframework.security.authentication.UsernamePasswordAuthenticationToken@441d0230: \
Principal: bob; Password: [PROTECTED]; \
Authenticated: true; Details: null; \
Granted Authorities: ROLE_USER
Note that you dont normally need to write any code like this. The process will normally occur internally,
in a web authentication filter for example. Weve just included the code here to show that the question
4.0.2.RELEASE
Spring Security
50
of what actually constitutes authentication in Spring Security has quite a simple answer. A user is
authenticated when the SecurityContextHolder contains a fully populated Authentication
object.
You can (and many users do) write their own filters or MVC controllers to provide interoperability
with authentication systems that are not based on Spring Security. For example, you might be using
Container-Managed Authentication which makes the current user available from a ThreadLocal or JNDI
location. Or you might work for a company that has a legacy proprietary authentication system, which
is a corporate "standard" over which you have little control. In situations like this its quite easy to
get Spring Security to work, and still provide authorization capabilities. All you need to do is write a
filter (or equivalent) that reads the third-party user information from a location, build a Spring Securityspecific Authentication object, and put it into the SecurityContextHolder. In this case you also
need to think about things which are normally taken care of automatically by the built-in authentication
infrastructure. For example, you might need to pre-emptively create an HTTP session to cache the
context between requests, before you write the response to the client footnote:[It isnt possible to create
a session once the response has been committed.
If youre wondering how the AuthenticationManager is implemented in a real world example, well
look at that in the core services chapter.
4.0.2.RELEASE
Spring Security
51
7. The original request that you made to cause the authentication process will be retried. Hopefully
youve authenticated with sufficient granted authorities to access the protected resource. If you have
sufficient access, the request will be successful. Otherwise, youll receive back an HTTP error code
403, which means "forbidden".
Spring Security has distinct classes responsible for most of the steps described above. The
main participants (in the order that they are used) are the ExceptionTranslationFilter, an
AuthenticationEntryPoint and an "authentication mechanism", which is responsible for calling
the AuthenticationManager which we saw in the previous section.
ExceptionTranslationFilter
ExceptionTranslationFilter is a Spring Security filter that has responsibility for detecting
any Spring Security exceptions that are thrown. Such exceptions will generally be thrown by an
AbstractSecurityInterceptor, which is the main provider of authorization services. We will
discuss AbstractSecurityInterceptor in the next section, but for now we just need to know that it
produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal.
Instead the ExceptionTranslationFilter offers this service, with specific responsibility for either
returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient
access - as per step seven above), or launching an AuthenticationEntryPoint (if the principal
has not been authenticated and therefore we need to go commence step three).
AuthenticationEntryPoint
The AuthenticationEntryPoint is responsible for step three in the above list. As you can imagine,
each web application will have a default authentication strategy (well, this can be configured like nearly
everything else in Spring Security, but lets keep it simple for now). Each major authentication system
will have its own AuthenticationEntryPoint implementation, which typically performs one of the
actions described in step 3.
Authentication Mechanism
Once your browser submits your authentication credentials (either as an HTTP form post or HTTP
header) there needs to be something on the server that"collects" these authentication details. By now
were at step six in the above list. In Spring Security we have a special name for the function of collecting
authentication details from a user agent (usually a web browser), referring to it as the "authentication
mechanism". Examples are form-base login and Basic authentication. Once the authentication details
have been collected from the user agent, an Authentication`"request" object is built
and then presented to the `AuthenticationManager.
After the authentication mechanism receives back the fully-populated Authentication object, it will
deem the request valid, put the Authentication into the SecurityContextHolder, and cause the
original request to be retried (step seven above). If, on the other hand, the AuthenticationManager
rejected the request, the authentication mechanism will ask the user agent to retry (step two above).
4.0.2.RELEASE
Spring Security
52
request and, crucially, clears the SecurityContextHolder when the request completes. You
shouldnt interact directly with the HttpSession for security purposes. There is simply no justification
for doing so - always use the SecurityContextHolder instead.
Many other types of application (for example, a stateless RESTful web service) do not use
HTTP sessions and will re-authenticate on every request. However, it is still important that
the SecurityContextPersistenceFilter is included in the chain to make sure that the
SecurityContextHolder is cleared after each request.
Note
In an application which receives concurrent requests in a single session, the same
SecurityContext instance will be shared between threads. Even though a ThreadLocal
is being used, it is the same instance that is retrieved from the HttpSession for
each thread. This has implications if you wish to temporarily change the context under
which a thread is running. If you just use SecurityContextHolder.getContext(),
and call setAuthentication(anAuthentication) on the returned context object,
then the Authentication object will change in all concurrent threads which
share the same SecurityContext instance. You can customize the behaviour of
SecurityContextPersistenceFilter to create a completely new SecurityContext for
each request, preventing changes in one thread from affecting another. Alternatively you can
create a new instance just at the point where you temporarily change the context. The method
SecurityContextHolder.createEmptyContext() always returns a new context instance.
4.0.2.RELEASE
Spring Security
53
4.0.2.RELEASE
Spring Security
54
method needs to call a remote system and present a different identity. Because Spring Security
automatically propagates security identity from one server to another (assuming youre using a properlyconfigured RMI or HttpInvoker remoting protocol client), this may be useful.
AfterInvocationManager
Following the secure object invocation proceeding and then returning - which may mean a method
invocation completing or a filter chain proceeding - the AbstractSecurityInterceptor gets one
final chance to handle the invocation. At this stage the AbstractSecurityInterceptor is interested
in possibly modifying the return object. We might want this to happen because an authorization
decision couldnt be made "on the way in" to a secure object invocation. Being highly pluggable,
AbstractSecurityInterceptor will pass control to an AfterInvocationManager to actually
modify the object if needed. This class can even entirely replace the object, or throw an exception, or not
change it in any way as it chooses. The after-invocation checks will only be executed if the invocation
is successful. If an exception occurs, the additional checks will be skipped.
AbstractSecurityInterceptor and its related objects are shown in Figure 7.1, Security
interceptors and the "secure object" model
4.0.2.RELEASE
Spring Security
55
7.6 Localization
Spring Security supports localization of exception messages that end users are likely to see. If your
application is designed for English-speaking users, you dont need to do anything as by default all
Security Security messages are in English. If you need to support other locales, everything you need
to know is contained in this section.
All exception messages can be localized, including messages related to authentication failures and
access being denied (authorization failures). Exceptions and logging messages that are focused on
developers or system deployers (including incorrect attributes, interface contract violations, using
incorrect constructors, startup time validation, debug-level logging) are not localized and instead are
hard-coded in English within Spring Securitys code.
Shipping
in
the
spring-security-core-xx.jar
you
will
find
an
org.springframework.security package that in turn contains a messages.properties
file, as well as localized versions for some common languages. This should be referred to by
your`ApplicationContext`, as Spring Security classes implement Springs MessageSourceAware
interface and expect the message resolver to be dependency injected at application context startup time.
Usually all you need to do is register a bean inside your application context to refer to the messages.
An example is shown below:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:org/springframework/security/messages"/>
</bean>
The messages.properties is named in accordance with standard resource bundles and represents
the default language supported by Spring Security messages. This default file is in English.
If you wish to customize the messages.properties file, or support other languages, you should copy
the file, rename it accordingly, and register it inside the above bean definition. There are not a large
number of message keys inside this file, so localization should not be considered a major initiative. If
you do perform localization of this file, please consider sharing your work with the community by logging
a JIRA task and attaching your appropriately-named localized version of messages.properties.
Spring Security relies on Springs localization support in order to actually lookup the appropriate
message. In order for this to work, you have to make sure that the locale from the incoming
request is stored in Springs org.springframework.context.i18n.LocaleContextHolder.
Spring MVCs DispatcherServlet does this for your application automatically, but since Spring
Securitys filters are invoked before this, the LocaleContextHolder needs to be set up to contain
the correct Locale before the filters are called. You can either do this in a filter yourself (which must
come before the Spring Security filters in`web.xml`) or you can use Springs RequestContextFilter.
Please refer to the Spring Framework documentation for further details on using localization with Spring.
4.0.2.RELEASE
Spring Security
56
4.0.2.RELEASE
Spring Security
57
8. Core Services
Now that we have a high-level overview of the Spring Security architecture and its core classes,
lets take a closer look at one or two of the core interfaces and their implementations, in particular
the AuthenticationManager, UserDetailsService and the AccessDecisionManager. These
crop up regularly throughout the remainder of this document so its important you know how they are
configured and how they operate.
In the above example we have three providers. They are tried in the order shown (which is implied
by the use of a List), with each provider able to attempt authentication, or skip authentication
by simply returning null. If all implementations return null, the ProviderManager will throw a
ProviderNotFoundException. If youre interested in learning more about chaining providers, please
refer to the ProviderManager JavaDocs.
Authentication mechanisms such as a web form-login processing filter are injected with a reference
to the ProviderManager and will call it to handle their authentication requests. The providers you
require will sometimes be interchangeable with the authentication mechanisms, while at other times they
will depend on a specific authentication mechanism. For example, DaoAuthenticationProvider
and LdapAuthenticationProvider are compatible with any mechanism which submits a simple
4.0.2.RELEASE
Spring Security
58
username/password authentication request and so will work with form-based logins or HTTP Basic
authentication. On the other hand, some authentication mechanisms create an authentication
request object which can only be interpreted by a single type of AuthenticationProvider.
An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so
can therefore only be authenticated by a CasAuthenticationProvider. You neednt be too
concerned about this, because if you forget to register a suitable provider, youll simply receive a
ProviderNotFoundException when an attempt to authenticate is made.
DaoAuthenticationProvider
The
simplest
AuthenticationProvider
implemented
by
Spring
Security
is
DaoAuthenticationProvider, which is also one of the earliest supported by the framework. It
leverages a UserDetailsService (as a DAO) in order to lookup the username, password and
GrantedAuthority s. It authenticates the user simply by comparing the password submitted in a
UsernamePasswordAuthenticationToken against the one loaded by the UserDetailsService.
Configuring the provider is quite simple:
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="inMemoryDaoImpl"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>
The returned UserDetails is an interface that provides getters that guarantee non-null provision of
authentication information such as the username, password, granted authorities and whether the user
account is enabled or disabled. Most authentication providers will use a`UserDetailsService`, even if
the username and password are not actually used as part of the authentication decision. They may use
4.0.2.RELEASE
Spring Security
59
the returned UserDetails object just for its GrantedAuthority information, because some other
system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the
credentials.
Given UserDetailsService is so simple to implement, it should be easy for users to retrieve
authentication information using a persistence strategy of their choice. Having said that, Spring Security
does include a couple of useful base implementations, which well look at below.
In-Memory Authentication
Is easy to use create a custom UserDetailsService implementation that extracts information from a
persistence engine of choice, but many applications do not require such complexity. This is particularly
true if youre building a prototype application or just starting integrating Spring Security, when you dont
really want to spend time configuring databases or writing UserDetailsService implementations.
For this sort of situation, a simple option is to use the user-service element from the security
namespace:
<user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
For example
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled
JdbcDaoImpl
Spring Security also includes a UserDetailsService that can obtain authentication information from
a JDBC data source. Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object
relational mapper (ORM) just to store user details. If your application does use an ORM tool, you might
prefer to write a custom UserDetailsService to reuse the mapping files youve probably already
created. Returning to JdbcDaoImpl, an example configuration is shown below:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
You can use different relational database management systems by modifying the
DriverManagerDataSource shown above. You can also use a global data source obtained from
JNDI, as with any other Spring configuration.
4.0.2.RELEASE
Spring Security
60
Authority Groups
By default, JdbcDaoImpl loads the authorities for a single user with the assumption that the authorities
are mapped directly to users (see the database schema appendix). An alternative approach is to partition
the authorities into groups and assign groups to the user. Some people prefer this approach as a means
of administering user rights. See the JdbcDaoImpl Javadoc for more information on how to enable the
use of group authorities. The group schema is also included in the appendix.
What is a hash?
Password hashing is not unique to Spring Security but is a common source of confusion for users who
are not familiar with the concept. A hash (or digest) algorithm is a one-way function which produces a
piece of fixed-length output data (the hash) from some input data, such as a password. As an example,
the MD5 hash of the string "password" (in hexadecimal) is
5f4dcc3b5aa765d61d8327deb882cf99
A hash is "one-way" in the sense that it is very difficult (effectively impossible) to obtain the original
input given the hash value, or indeed any possible input which would produce that hash value. This
property makes hash values very useful for authentication purposes. They can be stored in your user
database as an alternative to plaintext passwords and even if the values are compromised they do not
immediately reveal a password which can be used to login. Note that this also means you have no way
of recovering the password once it is encoded.
4.0.2.RELEASE
Spring Security
61
and huge dictionaries of these from previously hacked sites are available online. For example, if you
search for the hash value 5f4dcc3b5aa765d61d8327deb882cf99 using google, you will quickly
find the original word "password". In a similar way, an attacker can build a dictionary of hashes from
a standard word list and use this to lookup the original password. One way to help prevent this is to
have a suitably strong password policy to try to prevent common words from being used. Another is to
use a"salt" when calculating the hashes. This is an additional string of known data for each user which
is combined with the password before calculating the hash. Ideally the data should be as random as
possible, but in practice any salt value is usually preferable to none. Using a salt means that an attacker
has to build a separate dictionary of hashes for each salt value, making the attack more complicated
(but not impossible).
Bcrypt automatically generates a random salt value for each password when it is encoded, and stores
it in the bcrypt string in a standard format.
Note
The legacy approach to handling salt was to inject a SaltSource into the
DaoAuthenticationProvider, which would obtain a salt value for a particular user and pass
it to the PasswordEncoder. Using bcrypt means you dont have worry about the details of salt
handling (such as where the the value is stored), as it is all done internally. So wed strongly
recommend you use bcrypt unless you already have a system in place which stores the salt
separately.
4.0.2.RELEASE
Spring Security
62
The result of getMessage is a String saying "Hello" to the current Spring Security Authentication.
An example of the output is displayed below.
Hello org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360:
Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password:
[PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked:
true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null;
Granted Authorities: ROLE_USER
This is a basic example of how to setup Spring Security Test. The highlights are:
@RunWith instructs the spring-test module that it should create an ApplicationContext This is no
different than using the existing Spring Test support. For additional information, refer to the Spring
Reference
@ContextConfiguration instructs the spring-test the configuration to use to create the
ApplicationContext. Since no configuration is specified, the default configuration locations will
be tried. This is no different than using the existing Spring Test support. For additional information,
refer to the Spring Reference
Note
Spring
Security
hooks
into
Spring
Test
support
using
the
WithSecurityContextTestExecutionListener which will ensure our tests are ran with
the correct user. It does this by populating the SecurityContextHolder prior to running
our tests. After the test is done, it will clear out the SecurityContextHolder. If you
only need Spring Security related support, you can replace @ContextConfiguration with
@SecurityExecutionListeners.
Remember we added the @PreAuthorize annotation to our HelloMessageService and so it
requires an authenticated user to invoke it. If we ran the following test, we would expect the following
test will pass:
4.0.2.RELEASE
Spring Security
64
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void getMessageUnauthenticated() {
messageService.getMessage();
}
9.2 @WithMockUser
The question is "How could we most easily run the test as a specific user?" The answer is to use
@WithMockUser. The following test will be ran as a user with the username "user", the password
"password", and the roles "ROLE_USER".
@Test
@WithMockUser
public void getMessageWithMockUser() {
String message = messageService.getMessage();
...
}
in
the
SecurityContext
is
of
type
We can also easily customize the roles. For example, this test will be invoked with the username "admin"
and the roles "ROLE_USER" and "ROLE_ADMIN".
@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void getMessageWithMockUserCustomUser() {
String message = messageService.getMessage();
...
}
If we do not want the value to automatically be prefixed with ROLE_ we can leverage the authorities
attribute. For example, this test will be invoked with the username "admin" and the authorities "USER"
and "ADMIN".
@Test
@WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
public void getMessageWithMockUserCustomAuthorities() {
String message = messageService.getMessage();
...
}
4.0.2.RELEASE
Spring Security
65
Of course it can be a bit tedious placing the annotation on every test method. Instead, we can place
the annotation at the class level and every test will use the specified user. For example, the following
would run every test with a user with the username "admin", the password "password", and the roles
"ROLE_USER" and "ROLE_ADMIN".
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public class WithMockUserTests {
9.3 @WithUserDetails
While @WithMockUser is a very convenient way to get started, it may not work in all instances. For
example, it is common for applications to expect that the Authentication principal be of a specific
type. This is done so that the application can refer to the principal as the custom type and reduce
coupling on Spring Security.
The custom principal is often times returned by a custom UserDetailsService that returns an object
that implements both UserDetails and the custom type. For situations like this, it is useful to create the
test user using the custom UserDetailsService. That is exactly what @WithUserDetails does.
Assuming we have a UserDetailsService exposed as a bean, the following test will be invoked
with an Authentication of type UsernamePasswordAuthenticationToken and a principal that
is returned from the UserDetailsService with the username of "user".
@Test
@WithUserDetails
public void getMessageWithUserDetails() {
String message = messageService.getMessage();
...
}
We can also customize the username used to lookup the user from our UserDetailsService. For
example, this test would be executed with a principal that is returned from the UserDetailsService
with the username of "customUsername".
@Test
@WithUserDetails("customUsername")
public void getMessageWithUserDetailsCustomUsername() {
String message = messageService.getMessage();
...
}
Like @WithMockUser we can also place our annotation at the class level so that every test uses the
same user. However unlike @WithMockUser, @WithUserDetails requires the user to exist.
9.4 @WithSecurityContext
We have seen that @WithMockUser is an excellent choice if we are not using a custom
Authentication principal. Next we discovered that @WithUserDetails would allow us to use a
custom UserDetailsService to create our Authentication principal but required the user to exist.
We will now see an option that allows the most flexibility.
We can create our own annotation that uses the @WithSecurityContext to create
any SecurityContext we want. For example, we might create an annotation named
@WithMockCustomUser as shown below:
4.0.2.RELEASE
Spring Security
66
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithMockCustomUser {
String username() default "rob";
String name() default "Rob Winch";
}
We can now annotate a test class or a test method with our new annotation and Spring Securitys
WithSecurityContextTestExcecutionListener will ensure that our SecurityContext is
populated appropriately.
When creating your own WithSecurityContextFactory implementations, it is nice to
know that they can be annotated with standard Spring annotations. For example, the
WithUserDetailsSecurityContextFactory uses the @Autowired annotation to acquire the
UserDetailsService:
final class WithUserDetailsSecurityContextFactory
implements WithSecurityContextFactory<WithUserDetails> {
private UserDetailsService userDetailsService;
@Autowired
public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public SecurityContext createSecurityContext(WithUserDetails withUser) {
String username = withUser.value();
Assert.hasLength(username, "value() must be non empty String");
UserDetails principal = userDetailsService.loadUserByUsername(username);
Authentication authentication = new UsernamePasswordAuthenticationToken(principal,
principal.getPassword(), principal.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
return context;
}
}
4.0.2.RELEASE
Spring Security
67
10.2 SecurityMockMvcRequestPostProcessors
Spring MVC Test provides a convenient interface called a RequestPostProcessor that can be used
to modify a request. Spring Security provides a number of RequestPostProcessor implementations
that make testing easier. In order to use Spring Securitys RequestPostProcessor implementations
ensure the following static import is used:
import static
org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
4.0.2.RELEASE
Spring Security
68
mvc
.perform(post("/").with(csrf()))
If you like you can include CSRF token in the header instead:
mvc
.perform(post("/").with(csrf().asHeader()))
You can also test providing an invalid CSRF token using the following:
mvc
.perform(post("/").with(csrf().useInvalidToken()))
You can easily make customizations. For example, the following will run as a user (which does not
need to exist) with the username "admin", the password "pass", and the roles "ROLE_USER" and
"ROLE_ADMIN".
mvc
.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
If you have a custom UserDetails that you would like to use, you can easily specify that as well. For
example, the following will use the specified UserDetails (which does not need to exist) to run with
a UsernamePasswordAuthenticationToken that has a principal of the specified UserDetails:
mvc
.perform(get("/").with(user(userDetails)))
If you want a custom Authentication (which does not need to exist) you can do so using the following:
mvc
.perform(get("/").with(authentication(authentication)))
We can also ensure to run as a specific user for every request by using `MockMvcBuilderss default
request. For example, the following will run as a user (which does not need to exist) with the username
"admin", the password "password", and the role "ROLE_ADMIN":
4.0.2.RELEASE
Spring Security
69
mvc = MockMvcBuilders
.webAppContextSetup(context)
.defaultRequest(get("/").with(user("user").roles("ADMIN")))
.apply(springSecurity())
.build();
If you find you are using the same user in many of your tests, it is recommended to move
the user to a method. For example, you can specify the following in your own class named
CustomSecurityMockMvcRequestPostProcessors:
public static RequestPostProcessor rob() {
return user("rob").roles("ADMIN");
}
Now you can perform a static import on SecurityMockMvcRequestPostProcessors and use that
within your tests:
import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
...
mvc
.perform(get("/").with(rob()))
Alternatively, the following will run the test with the user with username "user", password "password",
and role "ROLE_ADMIN":
@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
mvc
.perform(get("/"))
...
}
will attempt to use HTTP Basic to authenticate a user with the username "user" and the password
"password" by ensuring the following header is populated on the HTTP Request:
4.0.2.RELEASE
Spring Security
70
10.3 SecurityMockMvcRequestBuilders
Spring MVC Test also provides a RequestBuilder interface that can be used to create the
MockHttpServletRequest used in your test. Spring Security provides a few RequestBuilder
implementations that can be used to make testing easier. In order to use Spring Securitys
RequestBuilder implementations ensure the following static import is used:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
It is easy to customize the request. For example, the following will submit a POST to "/auth" with the
username "admin", the password "pass", and a valid CSRF token:
mvc
.perform(formLogin("/auth").user("admin").password("pass"))
We can also customize the parameters names that the username and password are included on. For
example, this is the above request modified to include the username on the HTTP parameter "u" and
the password on the HTTP parameter "p".
mvc
.perform(formLogin("/auth").user("a","admin").password("p","pass"))
Testing Logout
While fairly trivial using standard Spring MVC Test, you can use Spring Securitys testing support to
make testing log out easier. For example, the following will submit a POST to "/logout" with a valid
CSRF token:
mvc
.perform(logout())
You can also customize the URL to post to. For example, the snippet below will submit a POST to "/
signout" with a valid CSRF token:
mvc
.perform(logout("/signout"))
10.4 SecurityMockMvcResultMatchers
At times it is desirable to make various security related assertions about a request. To accommodate this
need, Spring Security Test support implements Spring MVC Tests ResultMatcher interface. In order
to use Spring Securitys ResultMatcher implementations ensure the following static import is used:
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
4.0.2.RELEASE
Spring Security
71
Unauthenticated Assertion
At times it may be valuable to assert that there is no authenticated user associated with the result of a
MockMvc invocation. For example, you might want to test submitting an invalid username and password
and verify that no user is authenticated. You can easily do this with Spring Securitys testing support
using something like the following:
mvc
.perform(formLogin().password("invalid"))
.andExpect(unauthenticated());
Authenticated Assertion
It is often times that we must assert that an authenticated user exists. For example, we may want to
verify that we authenticated successfully. We could verify that a form based login was successful with
the following snippet of code:
mvc
.perform(formLogin())
.andExpect(authenticated());
If we wanted to assert the roles of the user, we could refine our previous code as shown below:
mvc
.perform(formLogin().user("admin"))
.andExpect(authenticated().withRoles("USER","ADMIN"));
4.0.2.RELEASE
Spring Security
72
11.1 DelegatingFilterProxy
When using servlet filters, you obviously need to declare them in your web.xml, or they will be ignored
by the servlet container. In Spring Security, the filter classes are also Spring beans defined in the
application context and thus able to take advantage of Springs rich dependency-injection facilities and
lifecycle interfaces. Springs DelegatingFilterProxy provides the link between web.xml and the
application context.
When using DelegatingFilterProxy, you will see something like this in the web.xml file:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Notice that the filter is actually a DelegatingFilterProxy, and not the class that will actually
implement the logic of the filter. What DelegatingFilterProxy does is delegate the Filters
methods through to a bean which is obtained from the Spring application
context. This enables the bean to benefit from the Spring web application
context lifecycle support and configuration flexibility. The bean must
implement `javax.servlet.Filter and it must have the same name as that in the filtername element. Read the Javadoc for DelegatingFilterProxy for more information
11.2 FilterChainProxy
Spring Securitys web infrastructure should only be used by delegating to an instance of
FilterChainProxy. The security filters should not be used by themselves. In theory you could
declare each Spring Security filter bean that you require in your application context file and add a
corresponding DelegatingFilterProxy entry to web.xml for each filter, making sure that they
are ordered correctly, but this would be cumbersome and would clutter up the web.xml file quickly
if you have a lot of filters. FilterChainProxy lets us add a single entry to web.xml and deal
entirely with the application context file for managing our web security beans. It is wired using a
4.0.2.RELEASE
Spring Security
74
DelegatingFilterProxy, just like in the example above, but with the filter-name set to the bean
name "filterChainProxy". The filter chain is then declared in the application context with the same bean
name. Heres an example:
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list>
<sec:filter-chain pattern="/restful/**" filters="
securityContextPersistenceFilterWithASCFalse,
basicAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
<sec:filter-chain pattern="/**" filters="
securityContextPersistenceFilterWithASCTrue,
formLoginFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
</list>
</constructor-arg>
</bean>
The namespace element filter-chain is used for convenience to set up the security filter chain(s)
1
which are required within the application. . It maps a particular URL pattern to a list of filters built
up from the bean names specified in the filters element, and combines them in a bean of type
SecurityFilterChain. The pattern attribute takes an Ant Paths and the most specific URIs should
2
appear first . At runtime the FilterChainProxy will locate the first URI pattern that matches the
current web request and the list of filter beans specified by the filters attribute will be applied to that
request. The filters will be invoked in the order they are defined, so you have complete control over the
filter chain which is applied to a particular URL.
You may have noticed we have declared two SecurityContextPersistenceFilter
s in the filter chain ( ASC is short for allowSessionCreation, a property of
SecurityContextPersistenceFilter). As web services will never present a jsessionid on
future requests, creating HttpSession s for such user agents would be wasteful. If you had a highvolume application which required maximum scalability, we recommend you use the approach shown
above. For smaller applications, using a single SecurityContextPersistenceFilter (with its
default allowSessionCreation as true) would likely be sufficient.
Note that FilterChainProxy does not invoke standard filter lifecycle methods on the filters it
is configured with. We recommend you use Springs application context lifecycle interfaces as an
alternative, just as you would for any other Spring bean.
When we looked at how to set up web security using namespace configuration, we used a
DelegatingFilterProxy with the name "springSecurityFilterChain". You should now be able to see
that this is the name of the FilterChainProxy which is created by the namespace.
Note that youll need to include the security namespace in your application context XML file in order to use this syntax. The older
syntax which used a filter-chain-map is still supported, but is deprecated in favour of the constructor argument injection.
2
Instead of a path pattern, the request-matcher-ref attribute can be used to specify a RequestMatcher instance for more
powerful matching
4.0.2.RELEASE
Spring Security
75
passed through the security filter chain. Otherwise the SecurityContextHolder will not have been
populated and the contents will be null.
4.0.2.RELEASE
Spring Security
76
exactly what the values of servletPath and pathInfo will contain for a particular request URI.
4
For example, each path segment of a URL may contain parameters, as defined in RFC 2396 .
The Specification does not clearly state whether these should be included in the servletPath and
pathInfo values and the behaviour varies between different servlet containers. There is a danger that
when an application is deployed in a container which does not strip path parameters from these values,
an attacker could add them to the requested URL in order to cause a pattern match to succeed or fail
5
unexpectedly. . Other variations in the incoming URL are also possible. For example, it could contain
path-traversal sequences (like /../) or multiple forward slashes (//) which could also cause patternmatches to fail. Some containers normalize these out before performing the servlet mapping, but others
dont. To protect against issues like these, FilterChainProxy uses an HttpFirewall strategy to
check and wrap the request. Un-normalized requests are automatically rejected by default, and path
6
parameters and duplicate slashes are removed for matching purposes. . It is therefore essential that
a FilterChainProxy is used to manage the security filter chain. Note that the servletPath and
pathInfo values are decoded by the container, so your application should not have any valid paths
which contain semi-colons, as these parts will be removed for matching purposes.
As mentioned above, the default strategy is to use Ant-style paths for matching and this is likely to be
the best choice for most users. The strategy is implemented in the class AntPathRequestMatcher
which uses Springs AntPathMatcher to perform a case-insensitive match of the pattern against the
concatenated servletPath and pathInfo, ignoring the queryString.
If for some reason, you need a more powerful matching strategy, you can use regular expressions.
The strategy implementation is then`RegexRequestMatcher`. See the Javadoc for this class for more
information.
In practice we recommend that you use method security at your service layer, to control access to your
application, and do not rely entirely on the use of security constraints defined at the web-application
level. URLs change and it is difficult to take account of all the possible URLs that an application might
support and how requests might be manipulated. You should try and restrict yourself to using a few
simple ant paths which are simple to understand. Always try to use a"deny-by-default" approach where
you have a catch-all wildcard ( / or ) defined last and denying access.
Security defined at the service layer is much more robust and harder to bypass, so you should always
take advantage of Spring Securitys method security options.
You have probably seen this when a browser doesnt support cookies and the jsessionid parameter is appended to the URL
after a semi-colon. However the RFC allows the presence of these parameters in any path segment of the URL
5
The original values will be returned once the request leaves the FilterChainProxy, so will still be available to the application.
6
So, for example, an original request path /secure;hack=1/somefile.html;hack=2 will be returned as /secure/
somefile.html.
4.0.2.RELEASE
Spring Security
77
internal FilterChainProxy and the URL pattern that should be mapped to it. The elements will be
added in the order they are declared, so the most specific patterns must again be declared first. Heres
another example, for a similar situation to that above, where the application supports both a stateless
RESTful API and also a normal web application which users log into using a form.
<!-- Stateless RESTful service using Basic authentication -->
<http pattern="/restful/**" create-session="stateless">
<intercept-url pattern='/**' access="hasRole('REMOTE')" />
<http-basic />
</http>
<!-- Empty filter chain for the login page -->
<http pattern="/login.htm*" security="none"/>
<!-- Additional filter chain for normal users, matching all other requests -->
<http>
<intercept-url pattern='/**' access="hasRole('USER')" />
<form-login login-page='/login.htm' default-target-url="/home.htm"/>
<logout />
</http>
4.0.2.RELEASE
Spring Security
78
12.1 FilterSecurityInterceptor
Weve already seen FilterSecurityInterceptor briefly when discussing access-control in
general, and weve already used it with the namespace where the <intercept-url> elements
are combined to configure it internally. Now well see how to explicitly configure it for use with
a`FilterChainProxy`, along with its companion filter ExceptionTranslationFilter. A typical
configuration example is shown below:
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
</security:filter-security-metadata-source>
</property>
</bean>
4.0.2.RELEASE
Spring Security
79
It is not possible to mix expression syntaxes within the same definition. As an example, the previous
configuration using regular expressions instead of Ant paths would be written as follows:
<bean id="filterInvocationInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="runAsManager" ref="runAsManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source request-matcher="regex">
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
</security:filter-security-metadata-source>
</property>
</bean>
Patterns are always evaluated in the order they are defined. Thus it is important that more specific
patterns are defined higher in the list than less specific patterns. This is reflected in our example above,
where the more specific /secure/super/ pattern appears higher than the less specific /secure/
pattern. If they were reversed, the /secure/ pattern would always match and the /secure/super/
pattern would never be evaluated.
12.2 ExceptionTranslationFilter
The ExceptionTranslationFilter sits above the FilterSecurityInterceptor in the security
filter stack. It doesnt do any actual security enforcement itself, but handles exceptions thrown by the
security interceptors and provides suitable and HTTP responses.
<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.htm"/>
</bean>
AuthenticationEntryPoint
The AuthenticationEntryPoint will be called if the user requests a secure HTTP resource but they
are not authenticated. An appropriate AuthenticationException or AccessDeniedException
will be thrown by a security interceptor further down the call stack, triggering the commence method
on the entry point. This does the job of presenting the appropriate response to the user so that
authentication can begin. The one weve used here is LoginUrlAuthenticationEntryPoint,
which redirects the request to a different URL (typically a login page). The actual implementation used
will depend on the authentication mechanism you want to be used in your application.
AccessDeniedHandler
What happens if a user is already authenticated and they try to access a protected resource? In normal
usage, this shouldnt happen because the application workflow should be restricted to operations to
which a user has access. For example, an HTML link to an administration page might be hidden from
4.0.2.RELEASE
Spring Security
80
users who do not have an admin role. You cant rely on hiding links for security though, as theres
always a possibility that a user will just enter the URL directly in an attempt to bypass the restrictions.
Or they might modify a RESTful URL to change some of the argument values. Your application must
be protected against these scenarios or it will definitely be insecure. You will typically use simple web
layer security to apply constraints to basic URLs and use more specific method-based security on your
service layer interfaces to really nail down what is permissible.
If an AccessDeniedException is thrown and a user has already been authenticated, then this means
that an operation has been attempted for which they dont have enough permissions. In this case,
ExceptionTranslationFilter will invoke a second strategy, the AccessDeniedHandler. By
default, an AccessDeniedHandlerImpl is used, which just sends a 403 (Forbidden) response to the
client. Alternatively you can configure an instance explicitly (as in the above example) and set an error
1
page URL which it will forwards the request to . This can be a simple "access denied" page, such
as a JSP, or it could be a more complex handler such as an MVC controller. And of course, you can
implement the interface yourself and use your own implementation.
Its also possible to supply a custom AccessDeniedHandler when youre using the namespace to
configure your application. See the namespace appendix for more details.
12.3 SecurityContextPersistenceFilter
We covered the purpose of this all-important filter in the Technical Overview chapter so you might want
to re-read that section at this point. Lets first take a look at how you would configure it for use with a
FilterChainProxy. A basic configuration only requires the bean itself
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
As we saw previously, this filter has two main tasks. It is responsible for storage of the
SecurityContext contents between HTTP requests and for clearing the SecurityContextHolder
1
We use a forward so that the SecurityContextHolder still contains details of the principal, which may be useful for displaying to
the user. In old releases of Spring Security we relied upon the servlet container to handle a 403 error message, which lacked
this useful contextual information.
4.0.2.RELEASE
Spring Security
81
when a request is completed. Clearing the ThreadLocal in which the context is stored is essential, as
it might otherwise be possible for a thread to be replaced into the servlet containers thread pool, with
the security context for a particular user still attached. This thread might then be used at a later stage,
performing operations with the wrong credentials.
SecurityContextRepository
From Spring Security 3.0, the job of loading and storing the security context is now delegated to a
separate strategy interface:
public interface SecurityContextRepository {
SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
void saveContext(SecurityContext context, HttpServletRequest request,
HttpServletResponse response);
}
The HttpRequestResponseHolder is simply a container for the incoming request and response
objects, allowing the implementation to replace these with wrapper classes. The returned contents will
be passed to the filter chain.
The default implementation is HttpSessionSecurityContextRepository, which stores the
2
security context as an HttpSession attribute . The most important configuration parameter for this
implementation is the allowSessionCreation property, which defaults to true, thus allowing the
class to create a session if it needs one to store the security context for an authenticated user (it
wont create one unless authentication has taken place and the contents of the security context have
changed). If you dont want a session to be created, then you can set this property to false:
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name='securityContextRepository'>
<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<property name='allowSessionCreation' value='false' />
</bean>
</property>
</bean>
12.4 UsernamePasswordAuthenticationFilter
Weve now seen the three main filters which are always present in a Spring Security web configuration.
These are also the three which are automatically created by the namespace <http> element and
cannot be substituted with alternatives. The only thing thats missing now is an actual authentication
mechanism, something that will allow a user to authenticate. This filter is the most commonly used
3
authentication filter and the one that is most often customized . It also provides the implementation used
by the <form-login> element from the namespace. There are three stages required to configure it.
2
In Spring Security 2.0 and earlier, this filter was called HttpSessionContextIntegrationFilter and performed all the
work of storing the context was performed by the filter itself. If you were familiar with this class, then most of the configuration
options which were available can now be found on`HttpSessionSecurityContextRepository`.
3
For historical reasons, prior to Spring Security 3.0, this filter was called AuthenticationProcessingFilter and the entry
point was called AuthenticationProcessingFilterEntryPoint. Since the framework now supports many different forms
of authentication, they have both been given more specific names in 3.0.
4.0.2.RELEASE
Spring Security
82
In versions prior to 3.0, the application flow at this point had evolved to a stage was controlled by a mix of properties on this class
and strategy plugins. The decision was made for 3.0 to refactor the code to make these two strategies entirely responsible.
4.0.2.RELEASE
Spring Security
83
HttpServletRequest.getUserPrincipal()
The
HttpServletRequest.getUserPrincipal()
will
return
the
result
of
SecurityContextHolder.getContext().getAuthentication(). This means it is an
Authentication which is typically an instance of UsernamePasswordAuthenticationToken
when using username and password based authentication. This can be useful if you need additional
information about your user. For example, you might have created a custom UserDetailsService
that returns a custom UserDetails containing a first and last name for your user. You could obtain
this information with the following:
Authentication auth = httpServletRequest.getUserPrincipal();
// assume integrated custom UserDetails called MyCustomUserDetails
// by default, typically instance of UserDetails
MyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();
String firstName = userDetails.getFirstName();
String lastName = userDetails.getLastName();
Note
It should be noted that it is typically bad practice to perform so much logic throughout your
application. Instead, one should centralize it to reduce any coupling of Spring Security and the
Servlet APIs.
HttpServletRequest.isUserInRole(String)
The
HttpServletRequest.isUserInRole(String)
will
determine
if
SecurityContextHolder.getContext().getAuthentication().getAuthorities()
contains a GrantedAuthority with the role passed into isUserInRole(String). Typically users
should not pass in the "ROLE_" prefix into this method since it is added automatically. For example,
if you want to determine if the current user has the authority "ROLE_ADMIN", you could use the the
following:
boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");
This might be useful to determine if certain UI components should be displayed. For example, you might
display admin links only if the current user is an admin.
4.0.2.RELEASE
Spring Security
84
HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)
The HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) method can be used
to ensure that a user is authenticated. If they are not authenticated, the configured
AuthenticationEntryPoint will be used to request the user to authenticate (i.e. redirect to the login page).
HttpServletRequest.login(String,String)
The HttpServletRequest.login(String,String) method can be used to authenticate the user with the
current AuthenticationManager. For example, the following would attempt to authenticate with the
username "user" and password "password":
try {
httpServletRequest.login("user","password");
} catch(ServletException e) {
// fail to authenticate
}
Note
It is not necessary to catch the ServletException if you want Spring Security to process the failed
authentication attempt.
HttpServletRequest.logout()
The HttpServletRequest.logout() method can be used to log the current user out.
Typically this means that the SecurityContextHolder will be cleared out, the HttpSession will be
invalidated, any "Remember Me" authentication will be cleaned up, etc. However, the configured
LogoutHandler implementations will vary depending on your Spring Security configuration. It is important
to note that after HttpServletRequest.logout() has been invoked, you are still in charge of writing a
response out. Typically this would involve a redirect to the welcome page.
AsyncContext.start(Runnable)
The AsynchContext.start(Runnable) method that ensures your credentials will be propagated to
the new Thread. Using Spring Securitys concurrency support, Spring Security overrides the
AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the
Runnable. For example, the following would output the current users Authentication:
final AsyncContext async = httpServletRequest.startAsync();
async.start(new Runnable() {
public void run() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
try {
final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();
asyncResponse.setStatus(HttpServletResponse.SC_OK);
asyncResponse.getWriter().write(String.valueOf(authentication));
async.complete();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
});
4.0.2.RELEASE
Spring Security
85
Next you need to ensure that your springSecurityFilterChain is setup for processing asynchronous
requests.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
Thats it! Now Spring Security will ensure that your SecurityContext is propagated on asynchronous
requests too.
So how does it work? If you are not really interested, feel free to skip the remainder of this section,
otherwise read on. Most of this is built into the Servlet specification, but there is a little bit of tweaking
that Spring Security does to ensure things work with asynchronous requests properly. Prior to Spring
Security 3.2, the SecurityContext from the SecurityContextHolder was automatically saved as soon as
the HttpServletResponse was committed. This can cause issues in a Async environment. For example,
consider the following:
httpServletRequest.startAsync();
new Thread("AsyncThread") {
@Override
public void run() {
try {
// Do work
TimeUnit.SECONDS.sleep(1);
// Write to and commit the httpServletResponse
httpServletResponse.getOutputStream().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
The issue is that this Thread is not known to Spring Security, so the SecurityContext is not propagated
to it. This means when we commit the HttpServletResponse there is no SecuriytContext. When Spring
Security automatically saved the SecurityContext on committing the HttpServletResponse it would lose
our logged in user.
4.0.2.RELEASE
Spring Security
86
Since version 3.2, Spring Security is smart enough to no longer automatically save the SecurityContext
on commiting the HttpServletResponse as soon as HttpServletRequest.startAsync() is invoked.
HttpServletRequest#changeSessionId()
The HttpServletRequest.changeSessionId() is the default method for protecting against Session
Fixation attacks in Servlet 3.1 and higher.
4.0.2.RELEASE
Spring Security
87
14.1 BasicAuthenticationFilter
BasicAuthenticationFilter is responsible for processing basic authentication credentials
presented in HTTP headers. This can be used for authenticating calls made by Spring remoting protocols
(such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet
Explorer). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11,
and BasicAuthenticationFilter conforms with this RFC. Basic Authentication is an attractive
approach to authentication, because it is very widely deployed in user agents and implementation is
extremely simple (its just a Base64 encoding of the username:password, specified in an HTTP header).
Configuration
To implement HTTP Basic Authentication, you need to add a BasicAuthenticationFilter to your
filter chain. The application context should contain BasicAuthenticationFilter and its required
collaborator:
<bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="Name Of Your Realm"/>
</bean>
14.2 DigestAuthenticationFilter
DigestAuthenticationFilter is capable of processing digest authentication credentials
presented in HTTP headers. Digest Authentication attempts to solve many of the weaknesses of
Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire.
Many user agents support Digest Authentication, including FireFox and Internet Explorer. The standard
4.0.2.RELEASE
Spring Security
88
governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of
the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617.
Spring Securitys DigestAuthenticationFilter is compatible with the auth quality of protection
(qop) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest
Authentication is a more attractive option if you need to use unencrypted HTTP (i.e. no TLS/HTTPS) and
wish to maximise security of the authentication process. Indeed Digest Authentication is a mandatory
requirement for the WebDAV protocol, as noted by RFC 2518 Section 17.1.
Digest Authentication is definitely the most secure choice between Form Authentication, Basic
Authentication and Digest Authentication, although extra security also means more complex user agent
implementations. Central to Digest Authentication is a "nonce". This is a value the server generates.
Spring Securitys nonce adopts the following format:
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
expirationTime:
The date and time when the nonce expires, expressed in milliseconds
key:
A private key to prevent modification of the nonce token
The DigestAuthenticatonEntryPoint has a property specifying the key used for generating the
nonce tokens, along with a nonceValiditySeconds property for determining the expiration time
(default 300, which equals five minutes). Whist ever the nonce is valid, the digest is computed by
concatenating various strings including the username, password, nonce, URI being requested, a clientgenerated nonce (merely a random value which the user agent generates each request), the realm name
etc, then performing an MD5 hash. Both the server and user agent perform this digest computation,
resulting in different hash codes if they disagree on an included value (eg password). In Spring Security
implementation, if the server-generated nonce has merely expired (but the digest was otherwise valid),
the DigestAuthenticationEntryPoint will send a "stale=true" header. This tells the user
agent there is no need to disturb the user (as the password and username etc is correct), but simply
to try again using a new nonce.
An appropriate value for DigestAuthenticationEntryPoints `nonceValiditySeconds
parameter will depend on your application. Extremely secure applications should note that an
intercepted authentication header can be used to impersonate the principal until the expirationTime
contained in the nonce is reached. This is the key principle when selecting an appropriate setting, but
it would be unusual for immensely secure applications to not be running over TLS/HTTPS in the first
instance.
Because of the more complex implementation of Digest Authentication, there are often user agent
issues. For example, Internet Explorer fails to present an opaque token on subsequent requests in
the same session. Spring Security filters therefore encapsulate all state information into the nonce
token instead. In our testing, Spring Securitys implementation works reliably with FireFox and Internet
Explorer, correctly handling nonce timeouts etc.
Configuration
Now that weve reviewed the theory, lets see how to use it. To implement HTTP Digest Authentication,
it is necessary to define DigestAuthenticationFilter in the filter chain. The application context
will need to define the DigestAuthenticationFilter and its required collaborators:
4.0.2.RELEASE
Spring Security
89
It is possible to encode the password in the format HEX( MD5(username:realm:password) ) provided the
DigestAuthenticationFilter.passwordAlreadyEncoded is set to true. However, other password encodings will not
work with digest authentication.
4.0.2.RELEASE
Spring Security
90
As such the remember-me token is valid only for the period specified, and provided that the username,
password and key does not change. Notably, this has a potential security issue in that a captured
remember-me token will be usable from any user agent until such time as the token expires. This is
the same issue as with digest authentication. If a principal is aware a token has been captured, they
can easily change their password and immediately invalidate all remember-me tokens on issue. If more
significant security is needed you should use the approach described in the next section. Alternatively
remember-me services should simply not be used at all.
If you are familiar with the topics discussed in the chapter on namespace configuration, you can enable
remember-me authentication just by adding the <remember-me> element:
<http>
...
<remember-me key="myAppKey"/>
</http>
The UserDetailsService will normally be selected automatically. If you have more than one in
your application context, you need to specify which one should be used with the user-service-ref
attribute, where the value is the name of your UserDetailsService bean.
4.0.2.RELEASE
Spring Security
91
The database should contain a persistent_logins table, created using the following SQL (or
equivalent):
create table persistent_logins (username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null)
Please refer to the JavaDocs for a fuller discussion on what the methods do, although
note at this stage that AbstractAuthenticationProcessingFilter only calls the
loginFail() and loginSuccess() methods. The autoLogin() method is called by
RememberMeAuthenticationFilter whenever the SecurityContextHolder does not contain
an Authentication. This interface therefore provides the underlying remember-me implementation
with sufficient notification of authentication-related events, and delegates to the implementation
whenever a candidate web request might contain a cookie and wish to be remembered. This design
allows any number of remember-me implementation strategies. Weve seen above that Spring Security
provides two implementations. Well look at these in turn.
TokenBasedRememberMeServices
This
implementation
supports
the
simpler
approach
described
in
Section 15.2, Simple Hash-Based Token Approach. TokenBasedRememberMeServices
generates
a
RememberMeAuthenticationToken,
which
is
processed
by
RememberMeAuthenticationProvider. A key is shared between this authentication provider
and the TokenBasedRememberMeServices. In addition, TokenBasedRememberMeServices
requires A UserDetailsService from which it can retrieve the username and password for signature
comparison purposes, and generate the RememberMeAuthenticationToken to contain the correct
1
Essentially, the username is not included in the cookie, to prevent exposing a valid login name unecessarily. There is a discussion
on this in the comments section of this article.
4.0.2.RELEASE
Spring Security
92
GrantedAuthority s. Some sort of logout command should be provided by the application that
invalidates the cookie if the user requests this. TokenBasedRememberMeServices also implements
Spring Securitys LogoutHandler interface so can be used with LogoutFilter to have the cookie
cleared automatically.
The beans required in an application context to enable remember-me services are as follows:
<bean id="rememberMeFilter" class=
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="theAuthenticationManager" />
</bean>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"/>
</bean>
Dont
forget
to
add
your
RememberMeServices
implementation
to
your
UsernamePasswordAuthenticationFilter.setRememberMeServices() property, include the
RememberMeAuthenticationProvider in your AuthenticationManager.setProviders()
list, and add RememberMeAuthenticationFilter into your FilterChainProxy (typically
immediately after your UsernamePasswordAuthenticationFilter).
PersistentTokenBasedRememberMeServices
This class can be used in the same way as TokenBasedRememberMeServices, but it additionally
needs to be configured with a PersistentTokenRepository to store the tokens. There are two
standard implementations.
InMemoryTokenRepositoryImpl which is intended for testing only.
JdbcTokenRepositoryImpl which stores the tokens in a database.
The database schema is described above in Section 15.3, Persistent Token Approach.
4.0.2.RELEASE
Spring Security
93
Now pretend you authenticate to your banks website and then, without logging out, visit an evil website.
The evil website contains an HTML page with the following form:
<form action="https://bank.example.com/transfer" method="post">
<input type="hidden"
name="amount"
value="100.00"/>
<input type="hidden"
name="routingNumber"
value="evilsRoutingNumber"/>
<input type="hidden"
name="account"
value="evilsAccountNumber"/>
<input type="submit"
value="Win Money!"/>
</form>
You like to win money, so you click on the submit button. In the process, you have unintentionally
transferred $100 to a malicious user. This happens because, while the evil website cannot see your
cookies, the cookies associated with your bank are still sent along with the request.
Worst yet, this whole process could have been automated using JavaScript. This means you didnt even
need to click on the button. So how do we protect ourselves from such attacks?
4.0.2.RELEASE
Spring Security
94
Additionally, we do not want to include the random token in HTTP GET as this can cause the tokens
to be leaked.
Lets take a look at how our example would change. Assume the randomly generated token is present
in an HTTP parameter named _csrf. For example, the request to transfer money would look like this:
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>
You will notice that we added the _csrf parameter with a random value. Now the evil website will not
be able to guess the correct value for the _csrf parameter (which must be explicitly provided on the evil
website) and the transfer will fail when the server compares the actual token to the expected token.
If an application were not validating the Content-Type, then it would be exposed to this exploit.
Depending on the setup, a Spring MVC application that validates the Content-Type could still be
exploited by updating the URL suffix to end with ".json" as shown below:
<form action="https://bank.example.com/transfer.json" method="post" enctype="text/plain">
<input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber",
"ignore_me":"' value='test"}' type='hidden'>
<input type="submit"
value="Win Money!"/>
</form>
4.0.2.RELEASE
Spring Security
95
For example, consider an application uses a custom cookie that contains all the state within it for
authentication instead of the JSESSIONID. When the CSRF attack is made the custom cookie will
be sent with the request in the same manner that the JSESSIONID cookie was sent in our previous
example.
Users using basic authentication are also vulnerable to CSRF attacks since the browser will
automatically include the username password in any requests in the same manner that the JSESSIONID
cookie was sent in our previous example.
CSRF protection is enabled by default with Java configuration. If you would like to disable CSRF,
the corresponding Java configuration can be seen below. Refer to the Javadoc of csrf() for additional
customizations in how CSRF protection is configured.
4.0.2.RELEASE
Spring Security
96
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
}
}
An easier approach is to use the csrfInput tag from the Spring Security JSP tag library.
Note
If you are using Spring MVC <form:form> tag or Thymeleaf 2.1+ and are using
@EnableWebSecurity, the CsrfToken is automatically included for you (using the
CsrfRequestDataValueProcessor).
Ajax and JSON Requests
If you are using JSON, then it is not possible to submit the CSRF token within an HTTP parameter.
Instead you can submit the token within a HTTP header. A typical pattern would be to include the CSRF
token within your meta tags. An example with a JSP is shown below:
<html>
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<!-- ... -->
</head>
<!-- ... -->
Instead of manually creating the meta tags, you can use the simpler csrfMetaTags tag from the Spring
Security JSP tag library.
You can then include the token within all your Ajax requests. If you were using jQuery, this could be
done with the following:
4.0.2.RELEASE
Spring Security
97
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
As an alternative to jQuery, we recommend using cujoJSs rest.js. The rest.js module provides advanced
support for working with HTTP requests and responses in RESTful ways. A core capability is the ability
to contextualize the HTTP client adding behavior as needed by chaining interceptors on to the client.
var client = rest.chain(csrf, {
token: $("meta[name='_csrf']").attr("content"),
name: $("meta[name='_csrf_header']").attr("content")
});
The configured client can be shared with any component of the application that needs to make a
request to the CSRF protected resource. One significant different between rest.js and jQuery is that only
requests made with the configured client will contain the CSRF token, vs jQuery where all requests will
include the token. The ability to scope which requests receive the token helps guard against leaking the
CSRF token to a third party. Please refer to the rest.js reference documentation for more information
on rest.js.
Timeouts
One issue is that the expected CSRF token is stored in the HttpSession, so as soon as the HttpSession
expires your configured AccessDeniedHandler will receive a InvalidCsrfTokenException. If you are
using the default AccessDeniedHandler, the browser will get an HTTP 403 and display a poor error
message.
Note
One might ask why the expected CsrfToken isnt stored in a cookie. This is because there are
known exploits in which headers (i.e. specify the cookies) can be set by another domain. This is
the same reason Ruby on Rails no longer skips CSRF checks when the header X-RequestedWith is present. See this webappsec.org thread for details on how to perform the exploit. Another
disadvantage is that by removing the state (i.e. the timeout) you lose the ability to forcibly terminate
the token if it is compromised.
A simple way to mitigate an active user experiencing a timeout is to have some JavaScript that lets
the user know their session is about to expire. The user can click a button to continue and refresh the
session.
Alternatively, specifying a custom AccessDeniedHandler allows you to process the
InvalidCsrfTokenException any way you like. For an example of how to customize the
AccessDeniedHandler refer to the provided links for both xml and Java configuration.
4.0.2.RELEASE
Spring Security
98
Logging In
In order to protect against forging log in requests the log in form should be protected against CSRF
attacks too. Since the CsrfToken is stored in HttpSession, this means an HttpSession will be created
as soon as CsrfToken token attribute is accessed. While this sounds bad in a RESTful / stateless
architecture the reality is that state is necessary to implement practical security. Without state, we have
nothing we can do if a token is compromised. Practically speaking, the CSRF token is quite small in
size and should have a negligible impact on our architecture.
Logging Out
Adding CSRF will update the LogoutFilter to only use HTTP POST. This ensures that log out requires
a CSRF token and that a malicious user cannot forcibly log out your users.
One approach is to use a form for log out. If you really want a link, you can use JavaScript to have the
link perform a POST (i.e. maybe on a hidden form). For browsers with JavaScript that is disabled, you
can optionally have the link take the user to a log out confirmation page that will perform the POST.
If you really want to use HTTP GET with logout you can do so, but remember this is generally not
recommended. For example, the following Java Configuration will perform logout with the URL /logout
is requested with any HTTP method:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
4.0.2.RELEASE
Spring Security
99
general, this is the recommended approach because the temporary file upload should have a negligble
impact on most servers.
To ensure MultipartFilter is specified before the Spring Security filter with java configuration, users
can override beforeSpringSecurityFilterChain as shown below:
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
To ensure MultipartFilter is specified before the Spring Security filter with XML configuration,
users can ensure the <filter-mapping> element of the MultipartFilter is placed before the
springSecurityFilterChain within the web.xml as shown below:
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The disadvantage to this approach is that query parameters can be leaked. More genearlly, it is
considered best practice to place sensitive data within the body or headers to ensure it is not leaked.
Additional information can be found in RFC 2616 Section 15.1.3 Encoding Sensitive Information in URIs.
HiddenHttpMethodFilter
The HiddenHttpMethodFilter should be placed before the Spring Security filter. In general this is true,
but it could have additional implications when protecting against CSRF attacks.
Note that the HiddenHttpMethodFilter only overrides the HTTP method on a POST, so this is actually
unlikely to cause any real problems. However, it is still best practice to ensure it is placed before Spring
Securitys filters.
4.0.2.RELEASE
Spring Security
100
For example, you can provide a custom CsrfTokenRepository to override the way in which the
CsrfToken is stored.
You can also specify a custom RequestMatcher to determine which requests are protected by CSRF
(i.e. perhaps you dont care if log out is exploited). In short, if Spring Securitys CSRF protection
doesnt behave exactly as you want it, you are able to customize the behavior. Refer to the the
section called <csrf> documentation for details on how to make these customizations with XML and
the CsrfConfigurer javadoc for details on how to make these customizations when using Java
configuration.
4.0.2.RELEASE
Spring Security
101
Note
Strict-Transport-Security is only added on HTTPS requests
For additional details on each of these headers, refer to the corresponding sections:
Cache Control
Content Type Options
HTTP Strict Transport Security
X-Frame-Options
X-XSS-Protection
While each of these headers are considered best practice, it should be noted that not all clients utilize
the headers, so additional testing is encouraged.
You can customize specific headers. For example, assume that want your HTTP response headers to
look like the following:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Specifically, you want all of the default headers with the following customizations:
X-Frame-Options to allow any request from same domain
HTTP Strict Transport Security (HSTS) will not be addded to the response
You can easily do this with the following Java Configuration:
4.0.2.RELEASE
Spring Security
102
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.frameOptions()
.sameOrigin()
.and()
.hsts().disable();
}
}
Alternatively, if you are using Spring Security XML Configuration, you can use the following:
<http>
<!-- ... -->
<headers>
<frame-options policy="SAMEORIGIN" />
<hsts disable="true"/>
</headers>
</http>
If you do not want the defaults to be added and want explicit control over what should be used, you can
disable the defaults. An example for both Java and XML based configuration is provided below:
If you are using Spring Securitys Java Configuration the following will only add Cache Control.
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
// do not use any default headers unless explicitly listed
.defaultsDisabled()
.cacheControl();
}
}
If necessary, you can disable all of the HTTP Security response headers with the following Java
Configuration:
4.0.2.RELEASE
Spring Security
103
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers().disable();
}
}
If necessary, you can disable all of the HTTP Security response headers with the following XML
configuration below:
<http>
<!-- ... -->
<headers disabled="true" />
</http>
Cache Control
In the past Spring Security required you to provide your own cache control for your web application.
This seemed reasonable at the time, but browser caches have evolved to include caches for secure
connections as well. This means that a user may view an authenticated page, log out, and then a
malicious user can use the browser history to view the cached page. To help mitigate this Spring Security
has added cache control support which will insert the following headers into you response.
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Simply adding the <headers> element with no child elements will automatically add Cache Control and
quite a few other protections. However, if you only want cache control, you can enable this feature
using Spring Securitys XML namespace with the <cache-control> element and the headers@defaultsdisabled attribute.
<http>
<!-- ... -->
<headers defaults-disable="true">
<cache-control />
</headers>
</http>
Similarly, you can enable only cache control within Java Configuration with the following:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.defaultsDisabled()
.cacheControl();
}
}
4.0.2.RELEASE
Spring Security
104
If you actually want to cache specific responses, your application can selectively invoke
HttpServletResponse.setHeader(String,String) to override the header set by Spring Security. This is
useful to ensure things like CSS, JavaScript, and images are properly cached.
When using Spring Web MVC, this is typically done within your configuration. For example, the following
configuration will ensure that the cache headers are set for all of your resources:
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31556926);
}
// ...
}
Just as with the cache control element, the nosniff directive is added by default when using the
<headers> element with no child elements. However, if you want more control over which headers are
added you can use the <content-type-options> element and the headers@defaults-disabled attribute
as shown below:
<http>
<!-- ... -->
<headers defaults-disabled="true">
<content-type-options />
</headers>
</http>
4.0.2.RELEASE
Spring Security
105
The X-Content-Type-Options header is added by default with Spring Security Java configuration. If you
want more control over the headers, you can explicitly specify the content type options with the following:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.defaultsDisabled()
.contentTypeOptions();
}
}
The optional includeSubDomains directive instructs Spring Security that subdomains (i.e.
secure.mybank.example.com) should also be treated as an HSTS domain.
As with the other headers, Spring Security adds HSTS by default. You can customize HSTS headers
with the <hsts> element as shown below:
<http>
<!-- ... -->
<headers>
<hsts
include-subdomains="true"
max-age-seconds="31536000" />
</headers>
</http>
4.0.2.RELEASE
Spring Security
106
Similarly, you can enable only HSTS headers with Java Configuration:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.httpStrictTransportSecurity()
.includeSubdomains(true)
.maxAgeSeconds(31536000);
}
}
X-Frame-Options
Allowing your website to be added to a frame can be a security issue. For example, using clever CSS
styling users could be tricked into clicking on something that they were not intending (video demo). For
example, a user that is logged into their bank might click a button that grants access to other users.
This sort of attack is known as Clickjacking.
Note
Another modern approach to dealing with clickjacking is using a Content Security Policy. Spring
Security does not provide support for this as the specification is not released and it is quite a
bit more complicated. However, you could use the static headers feature to implement this. To
stay up to date with this issue and to see how you can implement it with Spring Security refer
to SEC-2117
There are a number ways to mitigate clickjacking attacks. For example, to protect legacy browsers from
clickjacking attacks you can use frame breaking code. While not perfect, the frame breaking code is the
best you can do for the legacy browsers.
A more modern approach to address clickjacking is to use X-Frame-Options header:
X-Frame-Options: DENY
The X-Frame-Options response header instructs the browser to prevent any site with this header in the
response from being rendered within a frame. By default, Spring Security disables rendering within an
iframe.
You can customize X-Frame-Options with the frame-options element. For example, the following will
instruct Spring Security to use "X-Frame-Options: SAMEORIGIN" which allows iframes within the same
domain:
<http>
<!-- ... -->
<headers>
<frame-options
policy="SAMEORIGIN" />
</headers>
</http>
Similarly, you can customize frame options to use the same origin within Java Configuration using the
following:
4.0.2.RELEASE
Spring Security
107
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.frameOptions()
.sameOrigin();
}
}
X-XSS-Protection
Some browsers have built in support for filtering out reflected XSS attacks. This is by no means full
proof, but does assist in XSS protection.
The filtering is typically enabled by default, so adding the header typically just ensures it is enabled and
instructs the browser what to do when a XSS attack is detected. For example, the filter might try to
change the content in the least invasive way to still render everything. At times, this type of replacement
can become a XSS vulnerability in itself. Instead, it is best to block the content rather than attempt to
fix it. To do this we can add the following header:
X-XSS-Protection: 1; mode=block
This header is included by default. However, we can customize it if we wanted. For example:
<http>
<!-- ... -->
<headers>
<xss-protection block="false"/>
</headers>
</http>
Similarly, you can customize xss protection within Java Configuration with the following:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.xssProtection()
.block(false);
}
}
Static Headers
There may be times you wish to inject custom security headers into your application that are not
supported out of the box. For example, perhaps you wish to have early support for Content Security
4.0.2.RELEASE
Spring Security
108
Policy in order to ensure that resources are only loaded from the same origin. Since support for
Content Security Policy has not been finalized, browsers use one of two common extension headers to
implement the feature. This means we will need to inject the policy twice. An example of the headers
can be seen below:
X-Content-Security-Policy: default-src 'self'
X-WebKit-CSP: default-src 'self'
When using the XML namespace, these headers can be added to the response using the <header>
element as shown below:
<http>
<!-- ... -->
<headers>
<header name="X-Content-Security-Policy" value="default-src 'self'"/>
<header name="X-WebKit-CSP" value="default-src 'self'"/>
</headers>
</http>
Similarly, the headers could be added to the response using Java Configuration as shown in the
following:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy","default-src 'self'"))
.addHeaderWriter(new StaticHeadersWriter("X-WebKit-CSP","default-src 'self'"));
}
}
Headers Writer
When the namespace or Java configuration does not support the headers you want, you can create a
custom HeadersWriter instance or even provide a custom implementation of the HeadersWriter.
Lets take a look at an example of using an custom instance of XFrameOptionsHeaderWriter.
Perhaps you want to allow framing of content for the same origin. This is easily supported by setting the
policy attribute to "SAMEORIGIN", but lets take a look at a more explicit example using the ref attribute.
<http>
<!-- ... -->
<headers>
<header ref="frameOptionsWriter"/>
</headers>
</http>
<!-- Requires the c-namespace.
See http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-cnamespace
-->
<beans:bean id="frameOptionsWriter"
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
c:frameOptionsMode="SAMEORIGIN"/>
We could also restrict framing of content to the same origin with Java configuration:
4.0.2.RELEASE
Spring Security
109
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN));
}
}
DelegatingRequestMatcherHeaderWriter
At times you may want to only write a header for certain requests. For example, perhaps
you want to only protect your log in page from being framed. You could use the
DelegatingRequestMatcherHeaderWriter to do so. When using the XML namespace
configuration, this can be done with the following:
<http>
<!-- ... -->
<headers>
<frame-options disabled="true"/>
<header ref="headerWriter"/>
</headers>
</http>
<beans:bean id="headerWriter"
class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
<beans:constructor-arg>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
c:pattern="/login"/>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
</beans:constructor-arg>
</beans:bean>
We could also prevent framing of content to the log in page using java configuration:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher matcher = new AntPathRequestMatcher("/login");
DelegatingRequestMatcherHeaderWriter headerWriter =
new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
http
// ...
.headers()
.frameOptions().disabled()
.addHeaderWriter(headerWriter);
}
}
4.0.2.RELEASE
Spring Security
110
18.1 SessionManagementFilter
The SessionManagementFilter checks the contents of the SecurityContextRepository
against the current contents of the SecurityContextHolder to determine whether a user has
been authenticated during the current request, typically by a non-interactive authentication mechanism,
1
such as pre-authentication or remember-me . If the repository contains a security context, the filter
does nothing. If it doesnt, and the thread-local SecurityContext contains a (non-anonymous)
Authentication object, the filter assumes they have been authenticated by a previous filter in the
stack. It will then invoke the configured SessionAuthenticationStrategy.
If the user is not currently authenticated, the filter will check whether an invalid session ID has been
requested (because of a timeout, for example) and will invoke the configured`InvalidSessionStrategy`,
if one is set. The most common behaviour is just to redirect to a fixed URL and this is encapsulated
in the standard implementation`SimpleRedirectInvalidSessionStrategy`. The latter is also used when
configuring an invalid session URL through the namespace,as described earlier.
18.2 SessionAuthenticationStrategy
SessionAuthenticationStrategy is used by both SessionManagementFilter and
AbstractAuthenticationProcessingFilter, so if you are using a customized form-login class,
for example, you will need to inject it into both of these. In this case, a typical configuration, combining
the namespace and custom beans might look like this:
<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<session-management session-authentication-strategy-ref="sas"/>
</http>
<beans:bean id="myAuthFilter" class=
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
...
</beans:bean>
<beans:bean id="sas" class=
"org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
Note that the use of the default, SessionFixationProtectionStrategy may cause issues if you
are storing beans in the session which implement HttpSessionBindingListener, including Spring
session-scoped beans. See the Javadoc for this class for more information.
Authentication by mechanisms which perform a redirect after authenticating (such as form-login) will not be detected
by`SessionManagementFilter`, as the filter will not be invoked during the authenticating request. Session-management
functionality has to be handled separately in these cases.
4.0.2.RELEASE
Spring Security
111
network administrators like this feature because it helps prevent people from sharing login names. You
can, for example, stop user"Batman" from logging onto the web application from two different sessions.
You can either expire their previous login or you can report an error when they try to log in again,
preventing the second login. Note that if you are using the second approach, a user who has not explicitly
logged out (but who has just closed their browser, for example) will not be able to log in again until their
original session expires.
Concurrency control is supported by the namespace, so please check the earlier namespace chapter
for the simplest configuration. Sometimes you need to customize things though.
The implementation uses a specialized version of SessionAuthenticationStrategy, called
ConcurrentSessionControlAuthenticationStrategy.
Note
Previously the concurrent authentication check was made by the ProviderManager, which
could be injected with a ConcurrentSessionController. The latter would check if the user
was attempting to exceed the number of permitted sessions. However, this approach required that
an HTTP session be created in advance, which is undesirable. In Spring Security 3, the user is first
authenticated by the AuthenticationManager and once they are successfully authenticated, a
session is created and the check is made whether they are allowed to have another session open.
To use concurrent session support, youll need to add the following to web.xml:
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
In addition, you will need to add the ConcurrentSessionFilter to your FilterChainProxy. The
ConcurrentSessionFilter requires two properties, sessionRegistry, which generally points to
an instance of SessionRegistryImpl, and expiredUrl, which points to the page to display when
a session has expired. A configuration using the namespace to create the FilterChainProxy and
other default beans might look like this:
4.0.2.RELEASE
Spring Security
112
<http>
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<session-management session-authentication-strategy-ref="sas"/>
</http>
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/session-expired.htm" />
</beans:bean>
<beans:bean id="myAuthFilter" class=
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
4.0.2.RELEASE
Spring Security
113
19.2 Configuration
Anonymous authentication support is provided automatically when using the HTTP configuration Spring
Security 3.0 and can be customized (or disabled) using the <anonymous> element. You dont need to
configure the beans described here unless you are using traditional bean configuration.
Three
classes
that
together
provide
the
anonymous
authentication
feature.
AnonymousAuthenticationToken is an implementation of Authentication, and stores the
GrantedAuthority s which apply to the anonymous principal. There is a corresponding
AnonymousAuthenticationProvider, which is chained into the ProviderManager
so that AnonymousAuthenticationToken s are accepted. Finally, there is an
AnonymousAuthenticationFilter, which is chained after the normal authentication mechanisms
and automatically adds an AnonymousAuthenticationToken to the SecurityContextHolder if
there is no existing Authentication held there. The definition of the filter and authentication provider
appears as follows:
<bean id="anonymousAuthFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider"
class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/>
</bean>
4.0.2.RELEASE
Spring Security
114
The key is shared between the filter and authentication provider, so that tokens created by
1
the former are accepted by the latter . The userAttribute is expressed in the form of
usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]. This is
the same syntax as used after the equals sign for`InMemoryDaoImpls userMap property.
As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security
applied to them. For example:
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadata">
<security:filter-security-metadata-source>
<security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/**' access='ROLE_USER'/>
</security:filter-security-metadata-source>" +
</property>
</bean>
19.3 AuthenticationTrustResolver
Rounding out the anonymous authentication discussion is the AuthenticationTrustResolver
interface, with its corresponding AuthenticationTrustResolverImpl implementation. This
interface provides an isAnonymous(Authentication) method, which allows interested classes to
take into account this special type of authentication status. The ExceptionTranslationFilter uses
this interface in processing AccessDeniedException s. If an AccessDeniedException is thrown,
and the authentication is of an anonymous type, instead of throwing a 403 (forbidden) response, the filter
will instead commence the AuthenticationEntryPoint so the principal can authenticate properly.
This is a necessary distinction, otherwise principals would always be deemed "authenticated" and never
be given an opportunity to login via form, basic, digest or some other normal authentication mechanism.
You will often see the ROLE_ANONYMOUS attribute in the above interceptor configuration replaced
with IS_AUTHENTICATED_ANONYMOUSLY, which is effectively the same thing when defining access
controls. This is an example of the use of the AuthenticatedVoter which we will see in
the authorization chapter. It uses an AuthenticationTrustResolver to process this particular
configuration attribute and grant access to anonymous users. the AuthenticatedVoter approach
is more powerful, since it allows you to differentiate between anonymous, remember-me and
fully-authenticated users. If you dont need this functionality though, then you can stick with
ROLE_ANONYMOUS, which will be processed by Spring Securitys standard RoleVoter.
The use of the key property should not be regarded as providing any real security here. It is merely a book-keeping exercise.
If you are sharing a ProviderManager which contains an AnonymousAuthenticationProvider in a scenario where it is
possible for an authenticating client to construct the Authentication object (such as with RMI invocations), then a malicious
client could submit an AnonymousAuthenticationToken which it had created itself (with chosen username and authority list).
If the key is guessable or can be found out, then the token would be accepted by the anonymous provider. This isnt a problem with
normal usage but if you are using RMI you would be best to use a customized ProviderManager which omits the anonymous
provider rather than sharing the one you use for your HTTP authentication mechanisms.
4.0.2.RELEASE
Spring Security
115
Any inbound CONNECT message requires a valid CSRF token to enforce Same Origin Policy
The SecurityContextHolder is populated with the user within the simpUser header attribute for any
inbound request.
Our messages require the proper authorization. Specifically, any inbound message that starts with
"/user/" will require ROLE_USER. Additional details on authorization can be found in Section 20.3,
WebSocket Authorization
Spring Security also provides XML Namespace support for securing WebSockets. A comparable XML
based configuration looks like the following:
<websocket-message-broker>
Any inbound CONNECT message requires a valid CSRF token to enforce Same Origin Policy
4.0.2.RELEASE
Spring Security
116
The SecurityContextHolder is populated with the user within the simpUser header attribute for any
inbound request.
Our messages require the proper authorization. Specifically, any inbound message that starts with
"/user/" will require ROLE_USER. Additional details on authorization can be found in Section 20.3,
WebSocket Authorization
Any message without a destination (i.e. anything other that Message type of MESSAGE or
SUBSCRIBE) will require the user to be authenticated
Anyone can subscribe to /user/queue/errors
Any message that has a destination starting with "/app/" will be require the user to have the role
ROLE_USER
Any message that starts with "/user/" or "/topic/friends/" that is of type SUBSCRIBE will require
ROLE_USER
Any other message of type MESSAGE or SUBSCRIBE is rejected. Due to 6 we do not need this
step, but it illustrates how one can match on specific message types.
Any other Message is rejected. This is a good idea to ensure that you do not miss any messages.
Spring Security also provides XML Namespace support for securing WebSockets. A comparable XML
based configuration looks like the following:
4.0.2.RELEASE
Spring Security
117
<websocket-message-broker>
Any message of type CONNECT, UNSUBSCRIBE, or DISCONNECT will require the user to be
authenticated
Anyone can subscribe to /user/queue/errors
Any message that has a destination starting with "/app/" will be require the user to have the role
ROLE_USER
Any message that starts with "/user/" or "/topic/friends/" that is of type SUBSCRIBE will require
ROLE_USER
Any other message of type MESSAGE or SUBSCRIBE is rejected. Due to 6 we do not need this
step, but it illustrates how one can match on specific message types.
Any other message with a destination is rejected. This is a good idea to ensure that you do not
miss any messages.
4.0.2.RELEASE
Spring Security
118
Outbound Messages
Spring contains a section titled Flow of Messages that describes how messages flow through the system.
It is important to note that Spring Security only secures the clientInboundChannel. Spring Security
does not attempt to secure the clientOutboundChannel.
The most important reason for this is performance. For every message that goes in, there are typically
many many more that go out. Instead of securing the outbound messages, we encourage securing the
subscription to the endpoints.
4.0.2.RELEASE
Spring Security
119
If you are using static HTML, you can expose the CsrfToken on a REST endpoint. For example, the
following would expose the CsrfToken on the URL /csrf
@RestController
public class CsrfController {
@RequestMapping("/csrf")
public CsrfToken csrf(CsrfToken token) {
return token;
}
}
The javascript can make a REST call to the endpoint and use the response to populate the headerName
and the token.
We can now include the token in our Stomp client. For example:
...
var headers = {};
headers[headerName] = token;
stompClient.connect(headers, function(frame) {
...
}
4.0.2.RELEASE
Spring Security
120
Similarly, you can customize frame options to use the same origin within Java Configuration using the
following:
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.frameOptions()
.sameOrigin();
}
}
4.0.2.RELEASE
Spring Security
121
@Configuration
@EnableWebSecurity
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
// ignore our stomp endpoints since they are protected using Stomp headers
.ignoringAntMatchers("/chat/**")
.and()
.headers()
// allow same origin to frame our site to support iframe SockJS
.frameOptions().sameOrigin()
.and()
.authorizeRequests()
...
If we are using XML based configuration, we can use the csrf@request-matcher-ref. For example:
<http ...>
<csrf request-matcher-ref="csrfMatcher"/>
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
...
</http>
<b:bean id="csrfMatcher"
class="AndRequestMatcher">
<b:constructor-arg value="#{T(org.springframework.security.web.csrf.CsrfFilter).DEFAULT_MATCHER}"/>
<b:constructor-arg>
<b:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
<b:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<b:constructor-arg value="/chat/**"/>
</b:bean>
</b:bean>
</b:constructor-arg>
</b:bean>
4.0.2.RELEASE
Spring Security
122
The AccessDecisionManager
The AccessDecisionManager is called by the AbstractSecurityInterceptor and is
responsible for making final access control decisions. the AccessDecisionManager interface
contains three methods:
void decide(Authentication authentication, Object secureObject,
Collection<ConfigAttribute> attrs) throws AccessDeniedException;
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
The AccessDecisionManagers `decide method is passed all the relevant information it needs
in order to make an authorization decision. In particular, passing the secure Object enables those
4.0.2.RELEASE
Spring Security
124
arguments contained in the actual secure object invocation to be inspected. For example, lets assume
the secure object was a`MethodInvocation`. It would be easy to query the MethodInvocation for any
Customer argument, and then implement some sort of security logic in the AccessDecisionManager
to ensure the principal is permitted to operate on that customer. Implementations are expected to throw
an AccessDeniedException if access is denied.
The supports(ConfigAttribute) method is called by the AbstractSecurityInterceptor
at startup time to determine if the AccessDecisionManager can process the passed
ConfigAttribute. The supports(Class) method is called by a security interceptor implementation
to ensure the configured AccessDecisionManager supports the type of secure object that the security
interceptor will present.
4.0.2.RELEASE
Spring Security
125
Concrete implementations return an int, with possible values being reflected in the
AccessDecisionVoter static fields ACCESS_ABSTAIN, ACCESS_DENIED and ACCESS_GRANTED. A
voting implementation will return ACCESS_ABSTAIN if it has no opinion on an authorization decision. If
it does have an opinion, it must return either ACCESS_DENIED or ACCESS_GRANTED.
There are three concrete AccessDecisionManager s provided with Spring Security that tally the
votes. the ConsensusBased implementation will grant or deny access based on the consensus of
non-abstain votes. Properties are provided to control behavior in the event of an equality of votes
or if all votes are abstain. The AffirmativeBased implementation will grant access if one or more
ACCESS_GRANTED votes were received (i.e. a deny vote will be ignored, provided there was at least one
grant vote). Like the ConsensusBased implementation, there is a parameter that controls the behavior
if all voters abstain. The UnanimousBased provider expects unanimous ACCESS_GRANTED votes in
order to grant access, ignoring abstains. It will deny access if there is any ACCESS_DENIED vote. Like
the other implementations, there is a parameter that controls the behaviour if all voters abstain.
It is possible to implement a custom AccessDecisionManager that tallies votes differently. For
example, votes from a particular AccessDecisionVoter might receive additional weighting, whilst a
deny vote from a particular voter may have a veto effect.
RoleVoter
The most commonly used AccessDecisionVoter provided with Spring Security is the simple
RoleVoter, which treats configuration attributes as simple role names and votes to grant access if the
user has been assigned that role.
It will vote if any ConfigAttribute begins with the prefix ROLE_. It will vote to grant access if there
is a GrantedAuthority which returns a String representation (via the getAuthority() method)
exactly equal to one or more ConfigAttributes starting with the prefix ROLE_. If there is no exact
match of any ConfigAttribute starting with ROLE_, the RoleVoter will vote to deny access. If no
ConfigAttribute begins with ROLE_, the voter will abstain.
AuthenticatedVoter
Another voter which weve implicitly seen is the AuthenticatedVoter, which can be used to
differentiate between anonymous, fully-authenticated and remember-me authenticated users. Many
sites allow certain limited access under remember-me authentication, but require a user to confirm their
identity by logging in for full access.
When weve used the attribute IS_AUTHENTICATED_ANONYMOUSLY to grant anonymous access, this
attribute was being processed by the AuthenticatedVoter. See the Javadoc for this class for more
information.
Custom Voters
Obviously, you can also implement a custom AccessDecisionVoter and you can put just about any
access-control logic you want in it. It might be specific to your application (business-logic related) or
it might implement some security administration logic. For example, youll find a blog article on the
SpringSource web site which describes how to use a voter to deny access in real-time to users whose
accounts have been suspended.
4.0.2.RELEASE
Spring Security
126
illustrates
Spring
Securitys
4.0.2.RELEASE
Spring Security
127
want an admin to be able to do everything a normal user can. To achieve this, you can either make
sure that all admin users are also assigned the "user" role. Alternatively, you can modify every access
constraint which requires the "user" role to also include the "admin" role. This can get quite complicated
if you have a lot of different roles in your application.
The use of a role-hierarchy allows you to configure which roles (or authorities) should include others.
An extended version of Spring Securitys RoleVoter, RoleHierarchyVoter, is configured with a
RoleHierarchy, from which it obtains all the "reachable authorities" which the user is assigned. A
typical configuration might look like this:
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_ADMIN > ROLE_STAFF
ROLE_STAFF > ROLE_USER
ROLE_USER > ROLE_GUEST
</value>
</property>
</bean>
4.0.2.RELEASE
Spring Security
128
4.0.2.RELEASE
Spring Security
129
As you can see, aside from the class name, the AspectJSecurityInterceptor is
exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors
can share the same`securityMetadataSource`, as the SecurityMetadataSource works with
java.lang.reflect.Method s rather than an AOP library-specific class. Of course, your access
decisions have access to the relevant AOP library-specific invocation (ie MethodInvocation or
JoinPoint) and as such can consider a range of addition criteria when making access decisions (such
as method arguments).
Next youll need to define an AspectJ aspect. For example:
package org.springframework.security.samples.aspectj;
import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
import org.springframework.beans.factory.InitializingBean;
public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
private AspectJSecurityInterceptor securityInterceptor;
pointcut domainObjectInstanceExecution(): target(PersistableEntity)
&& execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect);
Object around(): domainObjectInstanceExecution() {
if (this.securityInterceptor == null) {
return proceed();
}
AspectJCallback callback = new AspectJCallback() {
public Object proceedWithObject() {
return proceed();
}
};
return this.securityInterceptor.invoke(thisJoinPoint, callback);
}
public AspectJSecurityInterceptor getSecurityInterceptor() {
return securityInterceptor;
}
public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
public void afterPropertiesSet() throws Exception {
if (this.securityInterceptor == null)
throw new IllegalArgumentException("securityInterceptor required");
}
}
}
4.0.2.RELEASE
Spring Security
130
In the above example, the security interceptor will be applied to every instance of
PersistableEntity, which is an abstract class not shown (you can use any other class or pointcut
expression you like). For those curious, AspectJCallback is needed because the proceed();
statement has special meaning only within an around() body. The AspectJSecurityInterceptor
calls this anonymous AspectJCallback class when it wants the target object to continue.
You will need to configure Spring to load the aspect and wire it with
AspectJSecurityInterceptor. A bean declaration which achieves this is shown below:
the
<bean id="domainObjectInstanceSecurityAspect"
class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
factory-method="aspectOf">
<property name="securityInterceptor" ref="bankManagerSecurity"/>
</bean>
Thats it! Now you can create your beans from anywhere within your application, using whatever means
you think fit (eg new Person();) and they will have the security interceptor applied.
4.0.2.RELEASE
Spring Security
131
23.1 Overview
Spring Security uses Spring EL for expression support and you should look at how that works if you are
interested in understanding the topic in more depth. Expressions are evaluated with a "root object" as
part of the evaluation context. Spring Security uses specific classes for web and method security as the
root object, in order to provide built-in expressions and access to values such as the current principal.
Description
hasRole([role])
hasAnyRole([role1,role2])
hasAuthority([authority])
hasAnyAuthority([authority1,authority2])
Returns true if the current principal has any of
the supplied roles (given as a comma-separated
list of strings)
principal
authentication
permitAll
4.0.2.RELEASE
Spring Security
132
Expression
Description
denyAll
isAnonymous()
isRememberMe()
isAuthenticated()
isFullyAuthenticated()
hasPermission(Object targetId,
String targetType, Object
permission)
Here we have defined that the "admin" area of an application (defined by the URL pattern) should
only be available to users who have the granted authority "admin" and whose IP address matches
a local subnet. Weve already seen the built-in hasRole expression in the previous section. The
expression hasIpAddress is an additional built-in expression which is specific to web security.
It is defined by the WebSecurityExpressionRoot class, an instance of which is used as the
expression root object when evaluation web-access expressions. This object also directly exposed
the HttpServletRequest object under the name request so you can invoke the request directly
in an expressio If expressions are being used, a WebExpressionVoter will be added to the
AccessDecisionManager which is used by the namespace. So if you arent using the namespace
and want to use expressions, you will have to add one of these to your configuration.
4.0.2.RELEASE
Spring Security
133
which means that access will only be allowed for users with the role "ROLE_USER". Obviously the same
thing could easily be achieved using a traditional configuration and a simple configuration attribute for
the required role. But what about:
@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);
Here were actually using a method argument as part of the expression to decide whether the current
user has the "admin"permission for the given contact. The built-in hasPermission() expression is
linked into the Spring Security ACL module through the application context, as wellsee below. You can
access any of the method arguments by name as expression variables.
There are a number of ways in which Spring Security can resolve the method arguments. Spring Security
uses DefaultSecurityParameterNameDiscoverer to discover the parameter names. By default,
the following options are tried for a method as a whole.
If Spring Securitys @P annotation is present on a single argument to the method, the value will be used.
This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain any information
about the parameter names. For example:
import org.springframework.security.access.method.P;
...
@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);
4.0.2.RELEASE
Spring Security
134
Here we are accessing another built-in expression, authentication, which is the Authentication
stored in the security context. You can also access its "principal" property directly, using the expression
principal. The value will often be a UserDetails instance, so you might use an expression like
principal.username or principal.enabled.
Less commonly, you may wish to perform an access-control check after the method has been invoked.
This can be achieved using the @PostAuthorize annotation. To access the return value from a
method, use the built-in name returnObject in the expression.
Filtering using @PreFilter and @PostFilter
As you may already be aware, Spring Security supports filtering of collections and arrays and this can
now be achieved using expressions. This is most commonly performed on the return value of a method.
For example:
@PreAuthorize("hasRole('USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List<Contact> getAll();
When using the @PostFilter annotation, Spring Security iterates through the returned collection and
removes any elements for which the supplied expression is false. The name filterObject refers
to the current object in the collection. You can also filter before the method call, using @PreFilter,
though this is a less common requirement. The syntax is just the same, but if there is more than one
argument which is a collection type then you have to select one by name using the filterTarget
property of this annotation.
Note that filtering is obviously not a substitute for tuning your data retrieval queries. If you are filtering
large collections and removing many of the entries then this is likely to be inefficient.
Built-In Expressions
There are some built-in expressions which are specific to method security, which we have already seen
in use above. The filterTarget and returnValue values are simple enough, but the use of the
hasPermission() expression warrants a closer look.
4.0.2.RELEASE
Spring Security
135
which map directly to the available versions of the expression, with the exception that the first argument
(the Authentication object) is not supplied. The first is used in situations where the domain object,
to which access is being controlled, is already loaded. Then expression will return true if the current
user has the given permission for that object. The second version is used in cases where the object is
not loaded, but its identifier is known. An abstract "type" specifier for the domain object is also required,
allowing the correct ACL permissions to be loaded. This has traditionally been the Java class of the
object, but does not have to be as long as it is consistent with how the permissions are loaded.
To use hasPermission() expressions, you have to explicitly configure a PermissionEvaluator
in your application context. This would look something like this:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class=
"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="myPermissionEvaluator"/>
</bean>
4.0.2.RELEASE
Spring Security
136
4.0.2.RELEASE
Spring Security
138
Spring Securitys domain object instance security capabilities centre on the concept of an access control
list (ACL). Every domain object instance in your system has its own ACL, and the ACL records details of
who can and cant work with that domain object. With this in mind, Spring Security delivers three main
ACL-related capabilities to your application:
A way of efficiently retrieving ACL entries for all of your domain objects (and modifying those ACLs)
A way of ensuring a given principal is permitted to work with your objects, before methods are called
A way of ensuring a given principal is permitted to work with your objects (or something they return),
after methods are called
As indicated by the first bullet point, one of the main capabilities of the Spring Security ACL module
is providing a high-performance way of retrieving ACLs. This ACL repository capability is extremely
important, because every domain object instance in your system might have several access control
entries, and each ACL might inherit from other ACLs in a tree-like structure (this is supported out-of-thebox by Spring Security, and is very commonly used). Spring Securitys ACL capability has been carefully
designed to provide high performance retrieval of ACLs, together with pluggable caching, deadlockminimizing database updates, independence from ORM frameworks (we use JDBC directly), proper
encapsulation, and transparent database updating.
Given databases are central to the operation of the ACL module, lets explore the four main tables used
by default in the implementation. The tables are presented below in order of size in a typical Spring
Security ACL deployment, with the table with the most rows listed last:
ACL_SID allows us to uniquely identify any principal or authority in the system ("SID" stands for
"security identity"). The only columns are the ID, a textual representation of the SID, and a flag to
indicate whether the textual representation refers to a principal name or a GrantedAuthority.
Thus, there is a single row for each unique principal or GrantedAuthority. When used in the
context of receiving a permission, a SID is generally called a "recipient".
ACL_CLASS allows us to uniquely identify any domain object class in the system. The only columns
are the ID and the Java class name. Thus, there is a single row for each unique Class we wish to
store ACL permissions for.
ACL_OBJECT_IDENTITY stores information for each unique domain object instance in the system.
Columns include the ID, a foreign key to the ACL_CLASS table, a unique identifier so we know which
ACL_CLASS instance were providing information for, the parent, a foreign key to the ACL_SID table
to represent the owner of the domain object instance, and whether we allow ACL entries to inherit
from any parent ACL. We have a single row for every domain object instance were storing ACL
permissions for.
Finally, ACL_ENTRY stores the individual permissions assigned to each recipient. Columns include
a foreign key to the ACL_OBJECT_IDENTITY, the recipient (ie a foreign key to ACL_SID), whether
well be auditing or not, and the integer bit mask that represents the actual permission being granted
or denied. We have a single row for every recipient that receives a permission to work with a domain
object.
As mentioned in the last paragraph, the ACL system uses integer bit masking. Dont worry, you need
not be aware of the finer points of bit shifting to use the ACL system, but suffice to say that we have 32
bits we can switch on or off. Each of these bits represents a permission, and by default the permissions
are read (bit 0), write (bit 1), create (bit 2), delete (bit 3) and administer (bit 4). Its easy to implement
your own Permission instance if you wish to use other permissions, and the remainder of the ACL
framework will operate without knowledge of your extensions.
4.0.2.RELEASE
Spring Security
139
It is important to understand that the number of domain objects in your system has absolutely no
bearing on the fact weve chosen to use integer bit masking. Whilst you have 32 bits available for
permissions, you could have billions of domain object instances (which will mean billions of rows in
ACL_OBJECT_IDENTITY and quite probably ACL_ENTRY). We make this point because weve found
sometimes people mistakenly believe they need a bit for each potential domain object, which is not
the case.
Now that weve provided a basic overview of what the ACL system does, and what it looks like at a table
structure, lets explore the key interfaces. The key interfaces are:
Acl: Every domain object has one and only one Acl object, which internally holds the
AccessControlEntry s as well as knows the owner of the Acl. An Acl does not refer
directly to the domain object, but instead to an ObjectIdentity. The Acl is stored in the
ACL_OBJECT_IDENTITY table.
AccessControlEntry: An Acl holds multiple AccessControlEntry s, which are often
abbreviated as ACEs in the framework. Each ACE refers to a specific tuple of`Permission`, Sid and
Acl. An ACE can also be granting or non-granting and contain audit settings. The ACE is stored in
the ACL_ENTRY table.
Permission: A permission represents a particular immutable bit mask, and offers convenience
functions for bit masking and outputting information. The basic permissions presented above (bits 0
through 4) are contained in the BasePermission class.
Sid: The ACL module needs to refer to principals and GrantedAuthority[] s. A level of
indirection is provided by the Sid interface, which is an abbreviation of "security identity". Common
classes include PrincipalSid (to represent the principal inside an Authentication object) and
GrantedAuthoritySid. The security identity information is stored in the ACL_SID table.
ObjectIdentity: Each domain object is represented internally within the ACL module by an
ObjectIdentity. The default implementation is called ObjectIdentityImpl.
AclService: Retrieves the Acl applicable for a given ObjectIdentity. In the included
implementation (JdbcAclService), retrieval operations are delegated to a LookupStrategy.
The LookupStrategy provides a highly optimized strategy for retrieving ACL information, using
batched retrievals (BasicLookupStrategy) and supporting custom implementations that leverage
materialized views, hierarchical queries and similar performance-centric, non-ANSI SQL capabilities.
MutableAclService: Allows a modified Acl to be presented for persistence. It is not essential to
use this interface if you do not wish.
Please note that our out-of-the-box AclService and related database classes all use ANSI SQL. This
should therefore work with all major databases. At the time of writing, the system had been successfully
tested using Hypersonic SQL, PostgreSQL, Microsoft SQL Server and Oracle.
Two samples ship with Spring Security that demonstrate the ACL module. The first is the Contacts
Sample, and the other is the Document Management System (DMS) Sample. We suggest taking a look
over these for examples.
4.0.2.RELEASE
Spring Security
140
In the example above, were retrieving the ACL associated with the "Foo" domain object with identifier
number 44. Were then adding an ACE so that a principal named "Samantha" can "administer" the
object. The code fragment is relatively self-explanatory, except the insertAce method. The first argument
to the insertAce method is determining at what position in the Acl the new entry will be inserted. In the
example above, were just putting the new ACE at the end of the existing ACEs. The final argument is
a boolean indicating whether the ACE is granting or denying. Most of the time it will be granting (true),
but if it is denying (false), the permissions are effectively being blocked.
Spring Security does not provide any special integration to automatically create, update or delete ACLs
as part of your DAO or repository operations. Instead, you will need to write code like shown above for
your individual domain objects. Its worth considering using AOP on your services layer to automatically
integrate the ACL information with your services layer operations. Weve found this quite an effective
approach in the past.
Once youve used the above techniques to store some ACL information in the database, the next step
is to actually use the ACL information as part of authorization decision logic. You have a number of
choices here. You could write your own AccessDecisionVoter or AfterInvocationProvider
that respectively fires before or after a method invocation. Such classes would use AclService
to retrieve the relevant ACL and then call Acl.isGranted(Permission[] permission,
Sid[] sids, boolean administrativeMode) to decide whether permission is granted or
4.0.2.RELEASE
Spring Security
141
4.0.2.RELEASE
Spring Security
142
AbstractPreAuthenticatedProcessingFilter
This class will check the current contents of the security context and, if empty, it will attempt to extract
user information from the HTTP request and submit it to the AuthenticationManager. Subclasses
override the following methods to obtain this information:
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
After calling these, the filter will create a PreAuthenticatedAuthenticationToken containing the
returned data and submit it for authentication. By "authentication" here, we really just mean further
processing to perhaps load the users authorities, but the standard Spring Security authentication
architecture is followed.
Like other Spring Security authentication filters, the pre-authentication filter has
an
authenticationDetailsSource
property
which
by
default
will
create
a
WebAuthenticationDetails object to store additional information such as the session-identifier and
originating IP address in the details property of the Authentication object. In cases where user
role information can be obtained from the pre-authentication mechanism, the data is also stored in this
4.0.2.RELEASE
Spring Security
143
property, with the details implementing the GrantedAuthoritiesContainer interface. This enables
the authentication provider to read the authorities which were externally allocated to the user. Well look
at a concrete example next.
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
If the filter is configured with an authenticationDetailsSource which is an instance of this
class, the authority information is obtained by calling the isUserInRole(String role) method
for each of a pre-determined set of "mappable roles". The class gets these from a configured
MappableAttributesRetriever. Possible implementations include hard-coding a list in the
application context and reading the role information from the <security-role> information in a
web.xml file. The pre-authentication sample application uses the latter approach.
There is an additional stage where the roles (or attributes) are mapped to Spring Security
GrantedAuthority objects using a configured Attributes2GrantedAuthoritiesMapper. The
default will just add the usual ROLE_ prefix to the names, but it gives you full control over the behaviour.
PreAuthenticatedAuthenticationProvider
The pre-authenticated provider has little more to do than load the UserDetails object for the user.
It does this by delegating to a AuthenticationUserDetailsService. The latter is similar to the
standard UserDetailsService but takes an Authentication object rather than just user name:
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
This interface may have also other uses but with pre-authentication it allows access to the authorities
which were packaged in the Authentication object, as we saw in the previous section. the
PreAuthenticatedGrantedAuthoritiesUserDetailsService class does this. Alternatively, it
may delegate to a standard UserDetailsService via the UserDetailsByNameServiceWrapper
implementation.
Http403ForbiddenEntryPoint
The AuthenticationEntryPoint was discussed in the technical overview chapter. Normally it is
responsible for kick-starting the authentication process for an unauthenticated user (when they try to
access a protected resource), but in the pre-authenticated case this doesnt apply. You would only
configure the ExceptionTranslationFilter with an instance of this class if you arent using preauthentication in combination with other authentication mechanisms. It will be called if the user is
rejected by the AbstractPreAuthenticatedProcessingFilter resulting in a null authentication.
It always returns a 403-forbidden response code if called.
4.0.2.RELEASE
Spring Security
144
Weve assumed here that the security namespace is being used for configuration. Its also assumed
that you have added a UserDetailsService (called "userDetailsService") to your configuration to
load the users roles.
4.0.2.RELEASE
Spring Security
145
4.0.2.RELEASE
Spring Security
146
Here weve specified that the root DIT of the directory should be "dc=springframework,dc=org", which
is the default. Used this way, the namespace parser will create an embedded Apache Directory server
and scan the classpath for any LDIF files, which it will attempt to load into the server. You can customize
this behaviour using the ldif attribute, which defines an LDIF resource to be loaded:
<ldap-server ldif="classpath:users.ldif" />
This makes it a lot easier to get up and running with LDAP, since it can be inconvenient to work all the
time with an external server. It also insulates the user from the complex bean configuration needed to
wire up an Apache Directory server. Using plain Spring Beans the configuration would be much more
cluttered. You must have the necessary Apache Directory dependency jars available for your application
to use. These can be obtained from the LDAP sample application.
This simple example would obtain the DN for the user by substituting the user login name in the supplied
pattern and attempting to bind as that user with the login password. This is OK if all your users are
stored under a single node in the directory. If instead you wished to configure an LDAP search filter to
locate the user, you could use the following:
<ldap-authentication-provider user-search-filter="(uid={0})"
user-search-base="ou=people"/>
If used with the server definition above, this would perform a search under the DN
ou=people,dc=springframework,dc=org using the value of the user-search-filter attribute
as a filter. Again the user login name is substituted for the parameter in the filter name, so it will search
for an entry with the uid attribute equal to the user name. If user-search-base isnt supplied, the
search will be performed from the root.
Loading Authorities
How authorities are loaded from groups in the LDAP directory is controlled by the following attributes.
group-search-base. Defines the part of the directory tree under which group searches should be
performed.
group-role-attribute. The attribute which contains the name of the authority defined by the
group entry. Defaults to`cn`
group-search-filter. The filter which is used to search for group membership. The default
2
is`uniqueMember={0}`, corresponding to the groupOfUniqueNames LDAP class . In this case, the
substituted parameter is the full distinguished name of the user. The parameter {1} can be used if
you want to filter on the login name.
4.0.2.RELEASE
Spring Security
147
LdapAuthenticator Implementations
The authenticator is also responsible for retrieving any required user attributes. This is because the
permissions on the attributes may depend on the type of authentication being used. For example, if
binding as the user, it may be necessary to read them with the users own permissions.
There are currently two authentication strategies supplied with Spring Security:
Authentication directly to the LDAP server ("bind" authentication).
Password comparison, where the password supplied by the user is compared with the one stored in
the repository. This can either be done by retrieving the value of the password attribute and checking
it locally or by performing an LDAP "compare" operation, where the supplied password is passed to
the server for comparison and the real password value is never retrieved.
Common Functionality
Before it is possible to authenticate a user (by either strategy), the distinguished name (DN) has to be
obtained from the login name supplied to the application. This can be done either by simple patternmatching (by setting the setUserDnPatterns array property) or by setting the userSearch property.
For the DN pattern-matching approach, a standard Java pattern format is used, and the login name
will be substituted for the parameter {0}. The pattern should be relative to the DN that the configured
SpringSecurityContextSource will bind to (see the section on connecting to the LDAP server
for more information on this). For example, if you are using an LDAP server with the URL`ldap://
monkeymachine.co.uk/dc=springframework,dc=org`, and have a pattern uid={0},ou=greatapes,
then a login name of "gorilla" will map to a DN`uid=gorilla,ou=greatapes,dc=springframework,dc=org`.
Each configured DN pattern will be tried in turn until a match is found. For information on using a search,
4.0.2.RELEASE
Spring Security
148
see the section on search objects below. A combination of the two approaches can also be used - the
patterns will be checked first and if no matching DN is found, the search will be used.
BindAuthenticator
The
class
BindAuthenticator
in
the
package
org.springframework.security.ldap.authentication implements the bind authentication
strategy. It simply attempts to bind as the user.
PasswordComparisonAuthenticator
The class PasswordComparisonAuthenticator
authentication strategy.
implements
the
password
comparison
LdapAuthoritiesPopulator
After authenticating the user successfully, the LdapAuthenticationProvider will attempt to load
a set of authorities for the user by calling the configured LdapAuthoritiesPopulator bean.
The DefaultLdapAuthoritiesPopulator is an implementation which will load the authorities by
searching the directory for groups of which the user is a member (typically these will be groupOfNames
or groupOfUniqueNames entries in the directory). Consult the Javadoc for this class for more details
on how it works.
If you want to use LDAP only for authentication, but load the authorities from a difference source (such
as a database) then you can provide your own implementation of this interface and inject that instead.
4.0.2.RELEASE
Spring Security
149
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
<property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
<property name="password" value="password"/>
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource"/>
<property name="userDnPatterns">
<list><value>uid={0},ou=people</value></list>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource"/>
<constructor-arg value="ou=groups"/>
<property name="groupRoleAttribute" value="ou"/>
</bean>
</constructor-arg>
</bean>
This would set up the provider to access an LDAP server with URL ldap://
monkeymachine:389/dc=springframework,dc=org. Authentication will be performed by
attempting to bind with the DN`uid=<user-login-name>,ou=people,dc=springframework,dc=org`. After
successful authentication, roles will be assigned to the user by searching under the DN
ou=groups,dc=springframework,dc=org with the default filter (member=<users-DN>). The
role name will be taken from the "ou" attribute of each match.
To configure a user search object, which uses the filter (uid=<user-login-name>) for use instead
of the DN-pattern (or in addition to it), you would configure the following bean
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value=""/>
<constructor-arg index="1" value="(uid={0})"/>
<constructor-arg index="2" ref="contextSource" />
</bean>
and use it by setting the BindAuthenticator beans userSearch property. The authenticator would
then call the search object to obtain the correct users DN before attempting to bind as this user.
4.0.2.RELEASE
Spring Security
150
Only the first method is relevant for authentication. If you provide an implementation of this interface and
inject it into the LdapAuthenticationProvider, you have control over exactly how the UserDetails
object is created. The first parameter is an instance of Spring LDAPs DirContextOperations which
gives you access to the LDAP attributes which were loaded during authentication. the username
parameter is the name used to authenticate and the final parameter is the collection of authorities loaded
for the user by the configured`LdapAuthoritiesPopulator`.
The way the context data is loaded varies slightly depending on the type of authentication you are
using. With the BindAuthenticator, the context returned from the bind operation will be used to read
the attributes, otherwise the data will be read using the standard context obtained from the configured
ContextSource (when a search is configured to locate the user, this will be the data returned by the
search object).
ActiveDirectoryLdapAuthenticationProvider
Configuring ActiveDirectoryLdapAuthenticationProvider is quite straightforward. You just
4
need to supply the domain name and an LDAP URL supplying the address of the server . An example
configuration would then look like this:
<bean id="adAuthenticationProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="mydomain.com" />
<constructor-arg value="ldap://adserver.mydomain.com/" />
</bean>
}
Note that there is no need to specify a separate ContextSource in order to define the server
location - the bean is completely self-contained. A user named "Sharon", for example, would
then be able to authenticate by entering either the username sharon or the full Active Directory
userPrincipalName, namely sharon@mydomain.com. The users directory entry will then be
located, and the attributes returned for possible use in customizing the created UserDetails object (a
UserDetailsContextMapper can be injected for this purpose, as described above). All interaction
with the directory takes place with the identity of the user themselves. There is no concept of a "manager"
user.
By default, the user authorities are obtained from the memberOf attribute values of the user entry. The
authorities allocated to the user can again be customized using a UserDetailsContextMapper. You
4
It is also possible to obtain the servers IP address using a DNS lookup. This is not currently supported, but hopefully will be
in a future version.
4.0.2.RELEASE
Spring Security
151
can also inject a GrantedAuthoritiesMapper into the provider instance to control the authorities
which end up in the Authentication object.
Active Directory Error Codes
By default, a failed result will cause a standard Spring Security BadCredentialsException. If you
set the property convertSubErrorCodesToExceptions to true, the exception messages will be
parsed to attempt to extract the Active Directory-specific error code and raise a more specific exception.
Check the class Javadoc for more information.
4.0.2.RELEASE
Spring Security
152
When used in conjuction with Spring Securitys PermissionEvaluator, the tag can also be used to check
permissions. For example:
<sec:authorize access="hasPermission(#domain,'read') or hasPermission(#domain,'write')">
This content will only be visible to users who have read or write permission to the Object found as a
request attribute named "domain".
</sec:authorize>
A common requirement is to only show a particular link, if the user is actually allowed to click it. How can
we determine in advance whether something will be allowed? This tag can also operate in an alternative
mode which allows you to define a particular URL as an attribute. If the user is allowed to invoke that
URL, then the tag body will be evaluated, otherwise it will be skipped. So you might have something like
<sec:authorize url="/admin">
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
</sec:authorize>
The legacy options from Spring Security 2.0 are also supported, but discouraged.
4.0.2.RELEASE
Spring Security
153
(such as the required roles) within your JSPs. This approach can also be combined with a method
attribute, supplying the HTTP method, for a more specific match.
The boolean result of evaluating the tag (whether it grants or denies access) can be stored in a page
context scope variable by setting the var attribute to the variable name, avoiding the need for duplicating
and re-evaluating the condition at other points in the page.
4.0.2.RELEASE
Spring Security
154
The permissions are passed to the PermissionFactory defined in the application context, converting
them to ACL Permission instances, so they may be any format which is supported by the factory - they
dont have to be integers, they could be strings like READ or WRITE. If no PermissionFactory is found,
an instance of DefaultPermissionFactory will be used. The AclService from the application
context will be used to load the Acl instance for the supplied object. The Acl will be invoked with the
required permissions to check if all of them are granted.
This tag also supports the var attribute, in the same way as the authorize tag.
4.0.2.RELEASE
Spring Security
155
<!DOCTYPE html>
<html>
<head>
<title>CSRF Protected JavaScript Page</title>
<meta name="description" content="This is the description for this page" />
<sec:csrfMetaTags />
<script type="text/javascript" language="javascript">
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
// using XMLHttpRequest directly to send an x-www-form-urlencoded request
var ajax = new XMLHttpRequest();
ajax.open("POST", "http://www.example.org/do/something", true);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded data");
ajax.send(csrfParameter + "=" + csrfToken + "&name=John&...");
// using XMLHttpRequest directly to send a non-x-www-form-urlencoded request
var ajax = new XMLHttpRequest();
ajax.open("POST", "http://www.example.org/do/something", true);
ajax.setRequestHeader(csrfHeader, csrfToken);
ajax.send("...");
// using JQuery to send an x-www-form-urlencoded request
var data = {};
data[csrfParameter] = csrfToken;
data["name"] = "John";
...
$.ajax({
url: "http://www.example.org/do/something",
type: "POST",
data: data,
...
});
// using JQuery to send a non-x-www-form-urlencoded request
var headers = {};
headers[csrfHeader] = csrfToken;
$.ajax({
url: "http://www.example.org/do/something",
type: "POST",
headers: headers,
...
});
<script>
</head>
<body>
...
</body>
</html>
4.0.2.RELEASE
Spring Security
156
28.2 AbstractJaasAuthenticationProvider
The AbstractJaasAuthenticationProvider is the basis for the provided JAAS
AuthenticationProvider implementations. Subclasses must implement a method that creates the
LoginContext. The AbstractJaasAuthenticationProvider has a number of dependencies
that can be injected into it that are discussed below.
JAAS CallbackHandler
Most JAAS LoginModule s require a callback of some sort. These callbacks are usually used to obtain
the username and password from the user.
In a Spring Security deployment, Spring Security is responsible for this user interaction (via the
authentication mechanism). Thus, by the time the authentication request is delegated through to JAAS,
Spring Securitys authentication mechanism will already have fully-populated an Authentication
object containing all the information required by the JAAS LoginModule.
Therefore, the JAAS package for Spring Security provides two default callback handlers,
JaasNameCallbackHandler and JaasPasswordCallbackHandler. Each of these callback
handlers implement JaasAuthenticationCallbackHandler. In most cases these callback
handlers can simply be used without understanding the internal mechanics.
For
those
needing
full
control
over
the
callback
behavior,
internally
AbstractJaasAuthenticationProvider
wraps
these
JaasAuthenticationCallbackHandler s with an InternalCallbackHandler. The
InternalCallbackHandler is the class that actually implements JAAS normal CallbackHandler
interface. Any time that the JAAS LoginModule is used, it is passed a list of
application context configured InternalCallbackHandler s. If the LoginModule requests
a callback against the InternalCallbackHandler s, the callback is in-turn passed to the
JaasAuthenticationCallbackHandler s being wrapped.
JAAS AuthorityGranter
JAAS works with principals. Even "roles" are represented as principals in JAAS. Spring Security, on the
other hand, works with Authentication objects. Each Authentication object contains a single
principal, and multiple GrantedAuthority s. To facilitate mapping between these different concepts,
Spring Securitys JAAS package includes an AuthorityGranter interface.
An AuthorityGranter is responsible for inspecting a JAAS principal and returning
a set of String s, representing the authorities assigned to the principal. For
each returned authority string, the AbstractJaasAuthenticationProvider creates a
4.0.2.RELEASE
Spring Security
157
28.3 DefaultJaasAuthenticationProvider
The DefaultJaasAuthenticationProvider allows a JAAS Configuration object to be
injected into it as a dependency. It then creates a LoginContext using the injected JAAS
Configuration. This means that DefaultJaasAuthenticationProvider is not bound any
particular implementation of Configuration as JaasAuthenticationProvider is.
InMemoryConfiguration
In order to make it easy to inject a Configuration into DefaultJaasAuthenticationProvider, a
default in memory implementation named InMemoryConfiguration is provided. The implementation
constructor accepts a Map where each key represents a login configuration name and the value
represents an Array of AppConfigurationEntry s. InMemoryConfiguration also supports a
default Array of AppConfigurationEntry objects that will be used if no mapping is found within the
provided Map. For details, refer to the class level javadoc of InMemoryConfiguration.
4.0.2.RELEASE
Spring Security
158
<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<map>
<!-SPRINGSECURITY is the default loginContextName
for AbstractJaasAuthenticationProvider
-->
<entry key="SPRINGSECURITY">
<array>
<bean class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg value="sample.SampleLoginModule" />
<constructor-arg>
<util:constant static-field=
"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
</constructor-arg>
<constructor-arg>
<map></map>
</constructor-arg>
</bean>
</array>
</entry>
</map>
</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
<!-- You will need to write your own implementation of AuthorityGranter -->
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
28.4 JaasAuthenticationProvider
The JaasAuthenticationProvider assumes the default Configuration is an instance
of ConfigFile. This assumption is made in order to attempt to update the Configuration.
The JaasAuthenticationProvider then uses the default Configuration to create the
LoginContext.
Lets assume we have a JAAS login configuration file, /WEB-INF/login.conf, with the following
contents:
JAASTest {
sample.SampleLoginModule required;
};
Like all Spring Security beans, the JaasAuthenticationProvider is configured via the application
context. The following definitions would correspond to the above JAAS login configuration file:
4.0.2.RELEASE
Spring Security
159
<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<property name="loginContextName" value="JAASTest"/>
<property name="callbackHandlers">
<list>
<bean
class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<bean
class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</list>
</property>
<property name="authorityGranters">
<list>
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
This integration can easily be configured using the jaas-api-provision attribute. This feature is useful
when integrating with legacy or external APIs that rely on the JAAS Subject being populated.
4.0.2.RELEASE
Spring Security
160
4.0.2.RELEASE
Spring Security
161
4.0.2.RELEASE
Spring Security
162
HTTPS connection will be used to send a proxy granting ticket to the original web application.
For example, https://server3.company.com/webapp/login/cas/proxyreceptor?pgtIou=PGTIOU-0R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH.
The Cas20TicketValidator will parse the XML received from the CAS server. It will return to the
CasAuthenticationProvider a TicketResponse, which includes the username (mandatory),
proxy list (if any were involved), and proxy-granting ticket IOU (if the proxy callback was requested).
Next CasAuthenticationProvider will call a configured CasProxyDecider. The
CasProxyDecider indicates whether the proxy list in the TicketResponse is acceptable to
the service. Several implementations are provided with Spring Security: RejectProxyTickets,
AcceptAnyCasProxy and NamedCasProxyDecider. These names are largely self-explanatory,
except NamedCasProxyDecider which allows a List of trusted proxies to be provided.
CasAuthenticationProvider will next request a AuthenticationUserDetailsService to
load the GrantedAuthority objects that apply to the user contained in the Assertion.
If
there
were
no
problems,
CasAuthenticationProvider
constructs
a
CasAuthenticationToken including the details contained in the TicketResponse and the
`GrantedAuthority`s.
Control then returns to CasAuthenticationFilter,
CasAuthenticationToken in the security context.
which
places
the
created
The users browser is redirected to the original page that caused the AuthenticationException
(or a custom destination depending on the configuration).
Its good that youre still here! Lets now look at how this is configured
The service must equal a URL that will be monitored by the CasAuthenticationFilter. The
sendRenew defaults to false, but should be set to true if your application is particularly sensitive. What
this parameter does is tell the CAS login service that a single sign on login is unacceptable. Instead, the
user will need to re-enter their username and password in order to gain access to the service.
4.0.2.RELEASE
Spring Security
163
The following beans should be configured to commence the CAS authentication process (assuming
youre using a namespace configuration):
<security:http entry-point-ref="casEntryPoint">
...
<security:custom-filter position="CAS_FILTER" ref="casFilter" />
</security:http>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://localhost:9443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
For
CAS
to
operate,
the
ExceptionTranslationFilter
must
have
its
authenticationEntryPoint property set to the CasAuthenticationEntryPoint bean.
This can easily be done using entry-point-ref as is done in the example above. The
CasAuthenticationEntryPoint must refer to the ServiceProperties bean (discussed above),
which provides the URL to the enterprises CAS login server. This is where the users browser will be
redirected.
The
CasAuthenticationFilter
has
very
similar
properties
to
the
UsernamePasswordAuthenticationFilter (used for form-based logins). You can use these
properties to customize things like behavior for authentication success and failure.
Next you need to add a CasAuthenticationProvider and its collaborators:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://localhost:9443/cas" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
<security:user-service id="userService">
<security:user name="joe" password="joe" authorities="ROLE_USER" />
...
</security:user-service>
4.0.2.RELEASE
Spring Security
164
This completes the most basic configuration for CAS. If you havent made any mistakes, your web
application should happily work within the framework of CAS single sign on. No other parts of Spring
Security need to be concerned about the fact CAS handled authentication. In the following sections we
will discuss some (optional) more advanced configurations.
Single Logout
The CAS protocol supports Single Logout and can be easily added to your Spring Security configuration.
Below are updates to the Spring Security configuration that handle Single Logout
<security:http entry-point-ref="casEntryPoint">
...
<security:logout logout-success-url="/cas-logout.jsp"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>
<!-- This filter handles a Single Logout Request from the CAS Server -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
<!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="https://localhost:9443/cas/logout"/>
<constructor-arg>
<bean class=
"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout/cas"/>
</bean>
The logout element logs the user out of the local application, but does not terminate the
session with the CAS server or any other applications that have been logged into. The
requestSingleLogoutFilter filter will allow the url of /spring_security_cas_logout to be
requested to redirect the application to the configured CAS Server logout url. Then the CAS Server will
send a Single Logout request to all the services that were signed into. The singleLogoutFilter
handles the Single Logout request by looking up the HttpSession in a static Map and then invalidating
it.
It might be confusing why both the logout element and the singleLogoutFilter are needed. It
is considered best practice to logout locally first since the SingleSignOutFilter just stores the
HttpSession in a static Map in order to call invalidate on it. With the configuration above, the flow of
logout would be:
The user requests /logout which would log the user out of the local application and send the user
to the logout success page.
The logout success page, /cas-logout.jsp, should instruct the user to click a link pointing to /
logout/cas in order to logout out of all applications.
When the user clicks the link, the user is redirected to the CAS single logout URL (https://
localhost:9443/cas/logout).
On the CAS Server side, the CAS single logout URL then submits single logout requests to all the
CAS Services. On the CAS Service side, JASIGs SingleSignOutFilter processes the logout
request by invaliditing the original session.
The next step is to add the following to your web.xml
4.0.2.RELEASE
Spring Security
165
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is
recommended to add the CharacterEncodingFilter to ensure that the character encoding is
correct when using the SingleSignOutFilter. Again, refer to JASIGs documentation for details. The
SingleSignOutHttpSessionListener ensures that when an HttpSession expires, the mapping
used for single logout is removed.
The next step is to update the CasAuthenticationProvider to be able to obtain proxy tickets.
To do this replace the Cas20ServiceTicketValidator with a Cas20ProxyTicketValidator.
The proxyCallbackUrl should be set to a URL that the application will receive PGTs at. Last, the
configuration should also reference the ProxyGrantingTicketStorage so it can use a PGT to obtain
proxy tickets. You can find an example of the configuration changes that should be made below.
4.0.2.RELEASE
Spring Security
166
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<constructor-arg value="https://localhost:9443/cas"/>
<property name="proxyCallbackUrl"
value="https://localhost:8443/cas-sample/login/cas/proxyreceptor"/>
<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
</bean>
</property>
</bean>
The last step is to update the CasAuthenticationFilter to accept PGT and to store them
in the ProxyGrantingTicketStorage. It is important the the proxyReceptorUrl matches the
proxyCallbackUrl of the Cas20ProxyTicketValidator. An example configuration is shown
below.
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
...
<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
<property name="proxyReceptorUrl" value="/login/cas/proxyreceptor"/>
</bean>
4.0.2.RELEASE
Spring Security
167
uses a StatelessTicketCache. This is used solely for stateless clients which use a
principal equal to CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER. What happens is
the CasAuthenticationProvider will store the resulting CasAuthenticationToken in the
StatelessTicketCache, keyed on the proxy ticket. Accordingly, remoting protocol clients can
present the same proxy ticket and the CasAuthenticationProvider will not need to contact the
CAS server for validation (aside from the first request). Once authenticated, the proxy ticket could be
used for URLs other than the original target service.
This section builds upon the previous sections to accomodate proxy ticket authentication. The first step
is to specify to authenticate all artifacts as shown below.
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
...
<property name="authenticateAllArtifacts" value="true"/>
</bean>
You will also need to update the CasAuthenticationProvider to handle proxy tickets. To do
this replace the Cas20ServiceTicketValidator with a Cas20ProxyTicketValidator. You will
need to configure the statelessTicketCache and which proxies you want to accept. You can find
an example of the updates required to accept all proxies below.
4.0.2.RELEASE
Spring Security
168
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<constructor-arg value="https://localhost:9443/cas"/>
<property name="acceptAnyProxy" value="true"/>
</bean>
</property>
<property name="statelessTicketCache">
<bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
<property name="cache">
<bean class="net.sf.ehcache.Cache"
init-method="initialise" destroy-method="dispose">
<constructor-arg value="casTickets"/>
<constructor-arg value="50"/>
<constructor-arg value="true"/>
<constructor-arg value="false"/>
<constructor-arg value="3600"/>
<constructor-arg value="900"/>
</bean>
</property>
</bean>
</property>
</bean>
4.0.2.RELEASE
Spring Security
169
4.0.2.RELEASE
Spring Security
170
The file server.jks contains the server certificate, private key and the issuing certificate authority
certificate. There are also some client certificate files for the users from the sample applications. You
can install these in your browser to enable SSL client authentication.
To run tomcat with SSL support, drop the server.jks file into the tomcat conf directory and add the
following connector to the server.xml file
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.home}/conf/server.jks"
keystoreType="JKS" keystorePass="password"
truststoreFile="${catalina.home}/conf/server.jks"
truststoreType="JKS" truststorePass="password"
/>
clientAuth can also be set to want if you still want SSL connections to succeed even if the client
doesnt provide a certificate. Clients which dont present a certificate wont be able to access any
objects secured by Spring Security unless you use a non-X.509 authentication mechanism, such as
form authentication.
4.0.2.RELEASE
Spring Security
171
31.2 Configuration
A RunAsManager interface is provided by Spring Security:
Authentication buildRunAs(Authentication authentication, Object object,
List<ConfigAttribute> config);
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
The first method returns the Authentication object that should replace the existing
Authentication object for the duration of the method invocation. If the method returns
null, it indicates no replacement should be made. The second method is used by the
AbstractSecurityInterceptor as part of its startup validation of configuration attributes. The
supports(Class) method is called by a security interceptor implementation to ensure the configured
RunAsManager supports the type of secure object that the security interceptor will present.
One concrete implementation of a RunAsManager is provided with Spring Security. The
RunAsManagerImpl class returns a replacement RunAsUserToken if any ConfigAttribute starts
with RUN_AS_. If any such ConfigAttribute is found, the replacement RunAsUserToken will
contain the same principal, credentials and granted authorities as the original Authentication
object, along with a new GrantedAuthorityImpl for each RUN_AS_ ConfigAttribute. Each new
GrantedAuthorityImpl will be prefixed with ROLE_, followed by the RUN_AS ConfigAttribute.
For example, a RUN_AS_SERVER will result in the replacement RunAsUserToken containing a
ROLE_RUN_AS_SERVER granted authority.
The replacement RunAsUserToken is just like any other Authentication object. It
needs to be authenticated by the AuthenticationManager, probably via delegation to a
suitable AuthenticationProvider. The RunAsImplAuthenticationProvider performs such
authentication. It simply accepts as valid any RunAsUserToken presented.
To ensure malicious code does not create a RunAsUserToken and present it for guaranteed
acceptance by the RunAsImplAuthenticationProvider, the hash of a key is stored in all
4.0.2.RELEASE
Spring Security
172
By using the same key, each RunAsUserToken can be validated it was created by an approved
RunAsManagerImpl. The RunAsUserToken is immutable after creation for security reasons
4.0.2.RELEASE
Spring Security
173
32.2 Encryptors
The Encryptors class provides factory methods for constructing symmetric encryptors. Using this class,
you can create ByteEncryptors to encrypt data in raw byte[] form. You can also construct TextEncryptors
to encrypt text strings. Encryptors are thread safe.
BytesEncryptor
Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor:
Encryptors.standard("password", "salt");
The "standard" encryption method is 256-bit AES using PKCS #5s PBKDF2 (Password-Based Key
Derivation Function #2). This method requires Java 6. The password used to generate the SecretKey
should be kept in a secure place and not be shared. The salt is used to prevent dictionary attacks against
the key in the event your encrypted data is compromised. A 16-byte random initialization vector is also
applied so each encrypted message is unique.
The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length.
Such a salt may be generated using a KeyGenerator:
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hexencoded
TextEncryptor
Use the Encryptors.text factory method to construct a standard TextEncryptor:
Encryptors.text("password", "salt");
A TextEncryptor uses a standard BytesEncryptor to encrypt text data. Encrypted results are returned
as hex-encoded strings for easy storage on the filesystem or in the database.
Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor:
Encryptors.queryableText("password", "salt");
The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with
initialization vector (iv) handling. The iv used in a queryable TextEncryptor#encrypt operation is shared,
or constant, and is not randomly generated. This means the same text encrypted multiple times will
always produce the same encryption result. This is less secure, but necessary for encrypted data that
needs to be queried against. An example of queryable encrypted text would be an OAuth apiKey.
4.0.2.RELEASE
Spring Security
174
BytesKeyGenerator
Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by
a SecureRandom instance:
KeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();
The default key length is 8 bytes. There is also a KeyGenerators.secureRandom variant that provides
control over the key length:
KeyGenerators.secureRandom(16);
Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns
the same key on every invocation:
KeyGenerators.shared(16);
StringKeyGenerator
Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that
hex-encodes each key as a String:
KeyGenerators.string();
The matches method returns true if the rawPassword, once encoded, equals the encodedPassword.
This method is designed to support password-based authentication schemes.
The BCryptPasswordEncoder implementation uses the widely supported "bcrypt" algorithm to hash
the passwords. Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order
to hinder password crackers. The amount of work it does can be tuned using the "strength" parameter
which takes values from 4 to 31. The higher the value, the more work has to be done to calculate the
hash. The default value is 10. You can change this value in your deployed system without affecting
existing passwords, as the value is also stored in the encoded hash.
// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
4.0.2.RELEASE
Spring Security
175
33.1 DelegatingSecurityContextRunnable
One of the most fundamental building blocks within Spring Securitys concurrency support is the
DelegatingSecurityContextRunnable. It wraps a delegate Runnable in order to initialize
the SecurityContextHolder with a specified SecurityContext for the delegate. It then
invokes the delegate Runnable ensuring to clear the SecurityContextHolder afterwards. The
DelegatingSecurityContextRunnable looks something like this:
public void run() {
try {
SecurityContextHolder.setContext(securityContext);
delegate.run();
} finally {
SecurityContextHolder.clearContext();
}
}
While very simple, it makes it seamless to transfer the SecurityContext from one Thread to another. This
is important since, in most cases, the SecurityContextHolder acts on a per Thread basis. For example,
you might have used Spring Securitys the section called <global-method-security> support to secure
one of your services. You can now easily transfer the SecurityContext of the current Thread to the
Thread that invokes the secured service. An example of how you might do this can be found below:
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured service
}
};
SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
new DelegatingSecurityContextRunnable(originalRunnable, context);
new Thread(wrappedRunnable).start();
4.0.2.RELEASE
Spring Security
176
The code we have is simple to use, but it still requires knowledge that we are using Spring Security. In
the next section we will take a look at how we can utilize DelegatingSecurityContextExecutor
to hide the fact that we are using Spring Security.
33.2 DelegatingSecurityContextExecutor
In
the
previous
section
we
found
that
it
was
easy
to
use
the
DelegatingSecurityContextRunnable, but it was not ideal since we had to be aware of Spring
Security in order to use it. Lets take a look at how DelegatingSecurityContextExecutor can
shield our code from any knowledge that we are using Spring Security.
The design of DelegatingSecurityContextExecutor is very similar to that of
DelegatingSecurityContextRunnable except it accepts a delegate Executor instead of a
delegate Runnable. You can see an example of how it might be used below:
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new UsernamePasswordAuthenticationToken("user","doesnotmatter",
AuthorityUtils.createAuthorityList("ROLE_USER"));
context.setAuthentication(authentication);
SimpleAsyncTaskExecutor delegateExecutor =
new SimpleAsyncTaskExecutor();
DelegatingSecurityContextExecutor executor =
new DelegatingSecurityContextExecutor(delegateExecutor, context);
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured service
}
};
executor.execute(originalRunnable);
4.0.2.RELEASE
Spring Security
177
At this point you may be asking yourself "How does this shield my code of any
knowledge of Spring Security?" Instead of creating the SecurityContext and the
DelegatingSecurityContextExecutor in our own code, we can inject an already initialized
instance of DelegatingSecurityContextExecutor.
@Autowired
private Executor executor; // becomes an instance of our DelegatingSecurityContextExecutor
public void submitRunnable() {
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured service
}
};
executor.execute(originalRunnable);
}
Now our code is unaware that the SecurityContext is being propagated to the Thread, then
the originalRunnable is executed, and then the SecurityContextHolder is cleared out. In
this example, the same user is being used to execute each Thread. What if we wanted to use the
user from SecurityContextHolder at the time we invoked executor.execute(Runnable) (i.e.
the currently logged in user) to process originalRunnable? This can be done by removing the
SecurityContext argument from our DelegatingSecurityContextExecutor constructor. For
example:
SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor();
DelegatingSecurityContextExecutor executor =
new DelegatingSecurityContextExecutor(delegateExecutor);
4.0.2.RELEASE
Spring Security
178
34.1 @EnableWebMvcSecurity
Note
As of Spring Security 4.0, @EnableWebMvcSecurity is deprecated. The replacement is
@EnableWebSecurity which will determine adding the Spring MVC features based upon the
classpath.
To enable Spring Security integration with Spring MVC add the @EnableWebSecurity annotation to
your configuration.
Note
Spring Security provides the configuration using Spring MVCs WebMvcConfigurerAdapter.
This means that if you are using more advanced options, like integrating with
WebMvcConfigurationSupport directly, then you will need to manually provide the Spring
Security configuration.
34.2 @AuthenticationPrincipal
Spring Security provides AuthenticationPrincipalArgumentResolver which can automatically
resolve the current Authentication.getPrincipal() for Spring MVC arguments. By using
Section 34.1, @EnableWebMvcSecurity you will automatically have this added to your Spring MVC
configuration. If you use XML based configuraiton, you must add this yourself.
Once AuthenticationPrincipalArgumentResolver is properly configured, you can be entirely
decoupled from Spring Security in your Spring MVC layer.
Consider a situation where a custom UserDetailsService that returns an Object that implements
UserDetails and your own CustomUser Object. The CustomUser of the currently authenticated
user could be accessed using the following code:
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
// ...
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser() {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
CustomUser custom = (CustomUser) authentication == null ? null : authentication.getPrincipal();
// .. find messags for this user and return them ...
}
As of Spring Security 3.2 we can resolve the argument more directly by adding an annotation. For
example:
4.0.2.RELEASE
Spring Security
179
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {
// .. find messags for this user and return them ...
}
Now that @CurrentUser has been specified, we can use it to signal to resolve our CustomUser of the
currently authenticated user. We have also isolated our dependency on Spring Security to a single file.
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@CurrentUser CustomUser customUser) {
// .. find messags for this user and return them ...
}
4.0.2.RELEASE
Spring Security
180
integrating with it. However, you can still use Concurrency Support to provide transparent integration
with Spring Security.
It is important to keep the CsrfToken a secret from other domains. This means if you are using Cross
Origin Sharing (CORS), you should NOT expose the CsrfToken to any external domains.
4.0.2.RELEASE
Spring Security
181
4.0.2.RELEASE
Spring Security
183
4.0.2.RELEASE
Spring Security
184
Group Authorities
Spring Security 2.0 introduced support for group authorities in JdbcDaoImpl. The table structure if
groups are enabled is as follows. You will need to adjust this schema to match the database dialect
you are using.
create table groups (
id bigint generated by default as identity(start with 0) primary key,
group_name varchar_ignorecase(50) not null
);
create table group_authorities (
group_id bigint not null,
authority varchar(50) not null,
constraint fk_group_authorities_group foreign key(group_id) references groups(id)
);
create table group_members (
id bigint generated by default as identity(start with 0) primary key,
username varchar(50) not null,
group_id bigint not null,
constraint fk_group_members_group foreign key(group_id) references groups(id)
);
Remember that these tables are only required if you are using the provided JDBC
UserDetailsService implementation. If you write your own or choose to implement
AuthenticationProvider without a UserDetailsService, then you have complete freedom over
how you store the data, as long as the interface contract is satisfied.
4.0.2.RELEASE
Spring Security
186
HyperSQL
The default schema works with the embedded HSQLDB database that is used in unit tests within the
framework.
4.0.2.RELEASE
Spring Security
187
4.0.2.RELEASE
Spring Security
188
PostgreSQL
create table acl_sid(
id bigserial not null primary key,
principal boolean not null,
sid varchar(100) not null,
constraint unique_uk_1 unique(sid,principal)
);
create table acl_class(
id bigserial not null primary key,
class varchar(100) not null,
constraint unique_uk_2 unique(class)
);
create table acl_object_identity(
id bigserial primary key,
object_id_class bigint not null,
object_id_identity bigint not null,
parent_object bigint,
owner_sid bigint,
entries_inheriting boolean not null,
constraint unique_uk_3 unique(object_id_class,object_id_identity),
constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
);
create table acl_entry(
id bigserial primary key,
acl_object_identity bigint not null,
ace_order int not null,
sid bigint not null,
mask integer not null,
granting boolean not null,
audit_success boolean not null,
audit_failure boolean not null,
constraint unique_uk_4 unique(acl_object_identity,ace_order),
constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
);
4.0.2.RELEASE
Spring Security
189
4.0.2.RELEASE
Spring Security
190
4.0.2.RELEASE
Spring Security
191
Oracle Database
CREATE TABLE acl_sid (
id NUMBER(38) NOT NULL PRIMARY KEY,
principal NUMBER(1) NOT NULL CHECK (principal in (0, 1)),
sid NVARCHAR2(100) NOT NULL,
CONSTRAINT unique_acl_sid UNIQUE (sid, principal)
);
CREATE SEQUENCE acl_sid_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_sid_id_trigger
BEFORE INSERT ON acl_sid
FOR EACH ROW
BEGIN
SELECT acl_sid_sequence.nextval INTO :new.id FROM dual;
END;
CREATE TABLE acl_class (
id NUMBER(38) NOT NULL PRIMARY KEY,
class NVARCHAR2(100) NOT NULL,
CONSTRAINT uk_acl_class UNIQUE (class)
);
CREATE SEQUENCE acl_class_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_class_id_trigger
BEFORE INSERT ON acl_class
FOR EACH ROW
BEGIN
SELECT acl_class_sequence.nextval INTO :new.id FROM dual;
END;
CREATE TABLE acl_object_identity (
id NUMBER(38) NOT NULL PRIMARY KEY,
object_id_class NUMBER(38) NOT NULL,
object_id_identity NUMBER(38) NOT NULL,
parent_object NUMBER(38),
owner_sid NUMBER(38),
entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity),
CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity
(id),
CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
);
CREATE SEQUENCE acl_object_identity_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_object_identity_id_trigger
BEFORE INSERT ON acl_object_identity
FOR EACH ROW
BEGIN
SELECT acl_object_identity_sequence.nextval INTO :new.id FROM dual;
END;
CREATE TABLE acl_entry (
id NUMBER(38) NOT NULL PRIMARY KEY,
acl_object_identity NUMBER(38) NOT NULL,
ace_order INTEGER NOT NULL,
sid NUMBER(38) NOT NULL,
mask INTEGER NOT NULL,
granting NUMBER(1) NOT NULL CHECK (granting in (0, 1)),
audit_success NUMBER(1) NOT NULL CHECK (audit_success in (0, 1)),
audit_failure NUMBER(1) NOT NULL CHECK (audit_failure in (0, 1)),
CONSTRAINT unique_acl_entry UNIQUE (acl_object_identity, ace_order),
CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
);
CREATE SEQUENCE acl_entry_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_entry_id_trigger
BEFORE INSERT ON acl_entry
FOR EACH ROW
BEGIN
SELECT acl_entry_sequence.nextval INTO :new.id FROM dual;
END;
4.0.2.RELEASE
Spring Security
192
<http>
If you use an <http> element within your application, a FilterChainProxy bean named
"springSecurityFilterChain" is created and the configuration within the element is used to build a filter
chain within FilterChainProxy. As of Spring Security 3.1, additional http elements can be used to
3
add extra filter chains . Some core filters are always created in a filter chain and others will be added
to the stack depending on the attributes and child elements which are present. The positions of the
standard filters are fixed (see the filter order table in the namespace introduction), removing a common
source of errors with previous versions of the framework when users had to configure the filter chain
explicitly in the FilterChainProxy bean. You can, of course, still do this if you need full control of
the configuration.
All filters which require a reference to the AuthenticationManager will be automatically injected with
the internal instance created by the namespace configuration (see the introductory chapter for more on
the AuthenticationManager).
Each <http> namespace block always creates an SecurityContextPersistenceFilter, an
ExceptionTranslationFilter and a FilterSecurityInterceptor. These are fixed and
cannot be replaced with alternatives.
<http> Attributes
The attributes on the <http> element control some of the properties on the core filters.
access-decision-manager-ref
Optional
attribute
specifying
the
ID
of
the
AccessDecisionManager implementation which should be used for authorizing HTTP requests.
By default an AffirmativeBased implementation is used for with a RoleVoter and an
AuthenticatedVoter.
3
See the introductory chapter for how to set up the mapping from your web.xml
4.0.2.RELEASE
Spring Security
193
property
of
pattern Defining a pattern for the http element controls the requests which will be filtered through the
list of filters which it defines. The interpretation is dependent on the configured request-matcher. If no
pattern is defined, all requests will be matched, so the most specific patterns should be declared first.
realm Sets the realm name used for basic authentication (if enabled). Corresponds to the realmName
property on BasicAuthenticationEntryPoint.
request-matcher Defines the RequestMatcher strategy used in the FilterChainProxy and
the beans created by the intercept-url to match incoming requests. Options are currently
ant, regex and ciRegex, for ant, regular-expression and case-insensitive regular-expression
repsectively. A separate instance is created for eachintercept-url element using its pattern and method
attributes. Ant paths are matched using an AntPathRequestMatcher and regular expressions are
matched using a RegexRequestMatcher. See the Javadoc for these classes for more details on
exactly how the matching is preformed. Ant paths are the default strategy.
request-matcher-ref A referenece to a bean that implements RequestMatcher that will determine
if this FilterChain should be used. This is a more powerful alternative to pattern.
4.0.2.RELEASE
Spring Security
194
security A request pattern can be mapped to an empty filter chain, by setting this attribute to none.
No security will be applied and none of Spring Securitys features will be available.
security-context-repository-ref Allows injection of a custom SecurityContextRepository into
the SecurityContextPersistenceFilter.
servlet-api-provision Provides versions of HttpServletRequest security methods such
as isUserInRole() and getPrincipal() which are implemented by adding a
SecurityContextHolderAwareRequestFilter bean to the stack. Defaults to true.
use-expressions Enables EL-expressions in the access attribute, as described in the chapter on
expression-based access-control. The default value is true.
Child Elements of <http>
access-denied-handler
anonymous
csrf
custom-filter
expression-handler
form-login
headers
http-basic
intercept-url
jee
logout
openid-login
port-mappings
remember-me
request-cache
session-management
x509
<access-denied-handler>
This element allows you to set the errorPage property for the default AccessDeniedHandler
used by the ExceptionTranslationFilter, using the error-page attribute, or to supply your
own implementation using theref attribute. This is discussed in more detail in the section on the
ExceptionTranslationFilter.
4.0.2.RELEASE
Spring Security
195
<headers>
This element allows for configuring additional (security) headers to be send with the response. It enables
easy configuration for several headers and also allows for setting custom headers through the header
element. Additional information, can be found in the Security Headers section of the reference.
Cache-Control, Pragma, and Expires - Can be set using the cache-control element. This ensures
that the browser does not cache your secured pages.
Strict-Transport-Security - Can be set using the hsts element. This ensures that the browser
automatically requests HTTPS for future requests.
X-Frame-Options - Can be set using the frame-options element. The X-Frame-Options header
can be used to prevent clickjacking attacks.
X-XSS-Protection - Can be set using the xss-protection element. The X-XSS-Protection header
can be used by browser to do basic control.
X-Content-Type-Options - Can be set using the content-type-options element. The X-ContentType-Options header prevents Internet Explorer from MIME-sniffing a response away from the
declared content-type. This also applies to Google Chrome, when downloading extensions.
<headers> Attributes
The attributes on the <headers> element control the headers element.
defaults-disabled Optional attribute that specifies to disable the default Spring Securitys HTTP
response headers. The default is false (the default headers are included).
disabled Optional attribute that specifies to disable Spring Securitys HTTP response headers. The
default is false (the headers are enabled).
Parent Elements of <headers>
http
Child Elements of <headers>
cache-control
content-type-options
frame-options
header
hsts
4.0.2.RELEASE
Spring Security
196
xss-protection
<cache-control>
Adds Cache-Control, Pragma, and Expires headers to ensure that the browser does not cache
your secured pages.
<cache-control> Attributes
disabled Specifies if Cache Control should be disabled. Default false.
Parent Elements of <cache-control>
headers
<hsts>
When enabled adds the Strict-Transport-Security header to the response for any secure request. This
allows the server to instruct browsers to automatically use HTTPS for future requests.
<hsts> Attributes
disabled Specifies if Strict-Transport-Security should be disabled. Default false.
include-sub-domains Specifies if subdomains should be included. Default true.
max-age-seconds Specifies the maximum ammount of time the host should be considered a Known
HSTS Host. Default one year.
request-matcher-ref The RequestMatcher instance to be used to determine if the header should be
set. Default is if HttpServletRequest.isSecure() is true.
Parent Elements of <hsts>
headers
<frame-options>
When enabled adds the X-Frame-Options header to the response, this allows newer browsers to do
some security checks and prevent clickjacking attacks.
<frame-options> Attributes
disabled If disabled, the X-Frame-Options header will not be included. Default false.
policy
DENY The page cannot be displayed in a frame, regardless of the site attempting to do so. This is
the default when frame-options-policy is specified.
SAMEORIGIN The page can only be displayed in a frame on the same origin as the page itself
ALLOW-FROM origin The page can only be displayed in a frame on the specified origin.
In other words, if you specify DENY, not only will attempts to load the page in a frame fail when loaded
from other sites, attempts to do so will fail when loaded from the same site. On the other hand, if you
4.0.2.RELEASE
Spring Security
197
specify SAMEORIGIN, you can still use the page in a frame as long as the site including it in a frame
it is the same as the one serving the page.
strategy Select the AllowFromStrategy to use when using the ALLOW-FROM policy.
static Use a single static ALLOW-FROM value. The value can be set through the value attribute.
regexp Use a regelur expression to validate incoming requests and if they are allowed. The regular
expression can be set through the value attribute. The request parameter used to retrieve the value
to validate can be specified using the from-parameter.
whitelist A comma-seperated list containing the allowed domains. The comma-seperated list
can be set through the value attribute. The request parameter used to retrieve the value to validate
can be specified using the from-parameter.
ref Instead of using one of the predefined strategies it is also possible to use a custom
AllowFromStrategy. The reference to this bean can be specified through this ref attribute.
value The value to use when ALLOW-FROM is used a strategy.
from-parameter Specify the name of the request parameter to use when using regexp or whitelist
for the ALLOW-FROM strategy.
Parent Elements of <frame-options>
headers
<xss-protection>
Adds the X-XSS-Protection header to the response to assist in protecting against reflected / Type-1
Cross-Site Scripting (XSS) attacks. This is in no-way a full protection to XSS attacks!
<xss-protection> Attributes
xss-protection-disabled Do not include the header for reflected / Type-1 Cross-Site Scripting (XSS)
protection.
xss-protection-enabled Explicitly enable or eisable reflected / Type-1 Cross-Site Scripting (XSS)
protection.
xss-protection-block When true and xss-protection-enabled is true, adds mode=block to the header.
This indicates to the browser that the page should not be loaded at all. When false and xss-protectionenabled is true, the page will still be rendered when an reflected attack is detected but the response
will be modified to protect against the attack. Note that there are sometimes ways of bypassing this
mode which can often times make blocking the page more desirable.
Parent Elements of <xss-protection>
headers
<content-type-options>
Add the X-Content-Type-Options header with the value of nosniff to the response. This disables MIMEsniffing for IE8+ and Chrome extensions.
4.0.2.RELEASE
Spring Security
198
<content-type-options> Attributes
disabled Specifies if Content Type Options should be disabled. Default false.
Parent Elements of <content-type-options>
headers
<header>
Add additional headers to the response, both the name and value need to be specified.
<header-attributes> Attributes
header-name The name of the header.
value The value of the header to add.
ref Reference to a custom implementation of the HeaderWriter interface.
Parent Elements of <header>
headers
<anonymous>
Adds
an
AnonymousAuthenticationFilter
AnonymousAuthenticationProvider.
Required
IS_AUTHENTICATED_ANONYMOUSLY attribute.
to
if
the
you
stack
are
and
using
an
the
<csrf>
This element will add Cross Site Request Forger (CSRF) protection to the application. It also updates
the default RequestCache to only replay "GET" requests upon successful authentication. Additional
information can be found in the Cross Site Request Forgery (CSRF) section of the reference.
4.0.2.RELEASE
Spring Security
199
to
use.
The
default
is
<custom-filter>
This element is used to add a filter to the filter chain. It doesnt create any additional beans but is used
to select a bean of type javax.servlet.Filter which is already defined in the application context
and add that at a particular position in the filter chain maintained by Spring Security. Full details can
be found in the namespace chapter.
Parent Elements of <custom-filter>
http
<custom-filter> Attributes
after The filter immediately after which the custom-filter should be placed in the chain. This feature
will only be needed by advanced users who wish to mix their own filters into the security filter chain
and have some knowledge of the standard Spring Security filters. The filter names map to specific
Spring Security implementation filters.
before The filter immediately before which the custom-filter should be placed in the chain
position The explicit position at which the custom-filter should be placed in the chain. Use if you are
replacing a standard filter.
ref Defines a reference to a Spring bean that implements Filter.
<expression-handler>
Defines the SecurityExpressionHandler instance which will be used if expression-based accesscontrol is enabled. A default implementation (with no ACL support) will be used if not supplied.
Parent Elements of <expression-handler>
global-method-security
http
websocket-message-broker
<expression-handler> Attributes
ref Defines a reference to a Spring bean that implements SecurityExpressionHandler.
4.0.2.RELEASE
Spring Security
200
<form-login>
Used to add an UsernamePasswordAuthenticationFilter to the filter stack and an
LoginUrlAuthenticationEntryPoint to the application context to provide authentication on
demand. This will always take precedence over other namespace-created entry points. If no attributes
16
are supplied, a login page will be generated automatically at the URL "/login" The behaviour can be
customized using the <form-login> Attributes.
Parent Elements of <form-login>
http
<form-login> Attributes
always-use-default-target If set to true, the user will always start at the value given
by default-target-url, regardless of how they arrived at the login page. Maps to the
alwaysUseDefaultTargetUrl property of UsernamePasswordAuthenticationFilter.
Default value is false.
authentication-details-source-ref Reference to an AuthenticationDetailsSource which will
be used by the authentication filter
authentication-failure-handler-ref Can be used as an alternative to authentication-failure-url, giving
you full control over the navigation flow after an authentication failure. The value should be he name
of an AuthenticationFailureHandler bean in the application context.
authentication-failure-url Maps to the authenticationFailureUrl property of
UsernamePasswordAuthenticationFilter. Defines the URL the browser will be redirected to
on login failure. Defaults to /login?error, which will be automatically handled by the automatic
login page generator, re-rendering the login page with an error message.
authentication-success-handler-ref This can be used as an alternative to defaulttarget-url and always-use-default-target, giving you full control over the navigation
flow after a successful authentication. The value should be the name of an
AuthenticationSuccessHandler bean in the application context. By default, an implementation
of SavedRequestAwareAuthenticationSuccessHandler is used and injected with the defaulttarget-url.
default-target-url
Maps
to
the
defaultTargetUrl
property
of
UsernamePasswordAuthenticationFilter. If not set, the default value is "/" (the application
root). A user will be taken to this URL after logging in, provided they were not asked to login while
attempting to access a secured resource, when they will be taken to the originally requested URL.
login-page The URL that should be used to render the login page. Maps to the loginFormUrl
property of the LoginUrlAuthenticationEntryPoint. Defaults to "/login".
login-processing-url
Maps
to
the
filterProcessesUrl
UsernamePasswordAuthenticationFilter. The default value is "/login".
property
of
password-parameter The name of the request parameter which contains the password. Defaults
to "password".
16
This feature is really just provided for convenience and is not intended for production (where a view technology will have been
chosen and can be used to render a customized login page). The class DefaultLoginPageGeneratingFilter is responsible
for rendering the login page and will provide login forms for both normal form login and/or OpenID if required.
4.0.2.RELEASE
Spring Security
201
username-parameter The name of the request parameter which contains the username. Defaults
to "username".
<http-basic>
Adds a BasicAuthenticationFilter and BasicAuthenticationEntryPoint to the
configuration. The latter will only be used as the configuration entry point if form-based login is not
enabled.
Parent Elements of <http-basic>
http
<http-basic> Attributes
authentication-details-source-ref Reference to an AuthenticationDetailsSource which will
be used by the authentication filter
entry-point-ref Sets the AuthenticationEntryPoint
BasicAuthenticationFilter.
which
is
used
by
the
<http-firewall> Element
This is a top-level element which can be used to inject a custom implementation of HttpFirewall into
the FilterChainProxy created by the namespace. The default implementation should be suitable
for most applications.
<http-firewall> Attributes
ref Defines a reference to a Spring bean that implements HttpFirewall.
<intercept-url>
This element is used to define the set of URL patterns that the application is
interested in and to configure how they should be handled. It is used to construct the
FilterInvocationSecurityMetadataSource used by the FilterSecurityInterceptor. It
is also responsible for configuring a ChannelProcessingFilter if particular URLs need to be
accessed by HTTPS, for example. When matching the specified patterns against an incoming request,
the matching is done in the order in which the elements are declared. So the most specific matches
patterns should come first and the most general should come last.
Parent Elements of <intercept-url>
filter-security-metadata-source
http
<intercept-url> Attributes
access
Lists
the
access
attributes
which
will
be
stored
in
the
FilterInvocationSecurityMetadataSource for the defined URL pattern/method
combination. This should be a comma-separated list of the security configuration attributes (such as
role names).
filters Can only take the value "none". This will cause any matching request to bypass the Spring
Security filter chain entirely. None of the rest of the <http> configuration will have any effect on the
4.0.2.RELEASE
Spring Security
202
request and there will be no security context available for its duration. Access to secured methods
during the request will fail.
Note
This property is invalid for filter-security-metadata-source
method The HTTP Method which will be used in combination with the pattern to match an incoming
request. If omitted, any method will match. If an identical pattern is specified with and without a method,
the method-specific match will take precedence.
pattern The pattern which defines the URL path. The content will depend on the request-matcher
attribute from the containing http element, so will default to ant path syntax.
requires-channel Can be "http" or "https" depending on whether a particular URL pattern should
be accessed over HTTP or HTTPS respectively. Alternatively the value "any" can be used when
there is no preference. If this attribute is present on any <intercept-url> element, then a
ChannelProcessingFilter will be added to the filter stack and its additional dependencies added
to the application context.
If a <port-mappings> configuration is added, this will be used to by the SecureChannelProcessor
and InsecureChannelProcessor beans to determine the ports used for redirecting to HTTP/HTTPS.
Note
This property is invalid for filter-security-metadata-source
<jee>
Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container
authentication.
Parent Elements of <jee>
http
<jee> Attributes
mappable-roles A comma-separate list of roles to look for in the incoming HttpServletRequest.
user-service-ref A reference to a user-service (or UserDetailsService bean) Id
<logout>
Adds
a
LogoutFilter
to
the
SecurityContextLogoutHandler.
filter
stack.
This
is
configured
with
4.0.2.RELEASE
Spring Security
203
invalidate-session
Maps
to
the
invalidateHttpSession
of
the
SecurityContextLogoutHandler. Defaults to "true", so the session will be invalidated on logout.
logout-success-url The destination URL which the user will be taken to after logging out. Defaults
to <form-login-login-page>/?logout (i.e. /login?logout)
Setting
this
attribute
will
inject
the
SessionManagementFilter
with
a
SimpleRedirectInvalidSessionStrategy configured with the attribute value. When an invalid
session ID is submitted, the strategy will be invoked, redirecting to the configured URL.
logout-url The URL which will cause a logout (i.e. which will be processed by the filter). Defaults
to "/logout".
success-handler-ref May be used to supply an instance of LogoutSuccessHandler which will be
invoked to control the navigation after logging out.
<openid-login>
Similar to <form-login> and has the same attributes. The default value for login-processing-url
is "/login/openid". An OpenIDAuthenticationFilter and OpenIDAuthenticationProvider
will be registered. The latter requires a reference to a UserDetailsService. Again, this can be
specified by id, using the user-service-ref attribute, or will be located automatically in the
application context.
Parent Elements of <openid-login>
http
<openid-login> Attributes
always-use-default-target Whether the user should always be redirected to the default-target-url
after login.
authentication-details-source-ref Reference to an AuthenticationDetailsSource which will be used
by the authentication filter
authentication-failure-handler-ref Reference to an AuthenticationFailureHandler bean which
should be used to handle a failed authentication request. Should not be used in combination with
authentication-failure-url as the implementation should always deal with navigation to the subsequent
destination
authentication-failure-url The URL for the login failure page. If no login failure URL is specified,
Spring Security will automatically create a failure login URL at /login?login_error and a corresponding
filter to render that login failure URL when requested.
authentication-success-handler-ref Reference to an AuthenticationSuccessHandler bean which
should be used to handle a successful authentication request. Should not be used in combination
with default-target-url (or always-use-default-target) as the implementation should always deal with
navigation to the subsequent destination
default-target-url The URL that will be redirected to after successful authentication, if the users
previous action could not be resumed. This generally happens if the user visits a login page without
having first requested a secured operation that triggers authentication. If unspecified, defaults to the
root of the application.
4.0.2.RELEASE
Spring Security
204
login-page The URL for the login page. If no login URL is specified, Spring Security will automatically
create a login URL at /login and a corresponding filter to render that login URL when requested.
login-processing-url The URL that the login form is posted to. If unspecified, it defaults to /login.
password-parameter The name of the request parameter which contains the password. Defaults
to "password".
user-service-ref A reference to a user-service (or UserDetailsService bean) Id
username-parameter The name of the request parameter which contains the username. Defaults
to "username".
Child Elements of <openid-login>
attribute-exchange
<attribute-exchange>
The attribute-exchange element defines the list of attributes which should be requested from
the identity provider. An example can be found in the OpenID Support section of the namespace
configuration chapter. More than one can be used, in which case each must have an identifiermatch attribute, containing a regular expression which is matched against the supplied OpenID
identifier. This allows different attribute lists to be fetched from different providers (Google, Yahoo etc).
Parent Elements of <attribute-exchange>
openid-login
<attribute-exchange> Attributes
identifier-match A regular expression which will be compared against the claimed identity, when
deciding which attribute-exchange configuration to use during authentication.
Child Elements of <attribute-exchange>
openid-attribute
<openid-attribute>
Attributes used when making an OpenID AX Fetch Request
Parent Elements of <openid-attribute>
attribute-exchange
<openid-attribute> Attributes
count Specifies the number of attributes that you wish to get back. For example, return 3 emails.
The default value is 1.
name Specifies the name of the attribute that you wish to get back. For example, email.
required Specifies if this attribute is required to the OP, but does not error out if the OP does not
return the attribute. Default is false.
4.0.2.RELEASE
Spring Security
205
type Specifies the attribute type. For example, http://axschema.org/contact/email. See your OPs
documentation for valid attribute types.
<port-mappings>
By default, an instance of PortMapperImpl will be added to the configuration for use in redirecting
to secure and insecure URLs. This element can optionally be used to override the default mappings
which that class defines. Each child <port-mapping> element defines a pair of HTTP:HTTPS ports.
The default mappings are 80:443 and 8080:8443. An example of overriding these can be found in the
namespace introduction.
Parent Elements of <port-mappings>
http
Child Elements of <port-mappings>
port-mapping
<port-mapping>
Provides a method to map http ports to https ports when forcing a redirect.
Parent Elements of <port-mapping>
port-mappings
<port-mapping> Attributes
http The http port to use.
https The https port to use.
<remember-me>
Adds the RememberMeAuthenticationFilter to the stack. This in turn will be configured with
either a TokenBasedRememberMeServices, a PersistentTokenBasedRememberMeServices
or a user-specified bean implementing RememberMeServices depending on the attribute settings.
Parent Elements of <remember-me>
http
<remember-me> Attributes
authentication-success-handler-ref Sets the authenticationSuccessHandler property on
the RememberMeAuthenticationFilter if custom navigation is required. The value should be
the name of a AuthenticationSuccessHandler bean in the application context.
data-source-ref
A
reference
to
a
DataSource
bean.
If
this
is
set,
PersistentTokenBasedRememberMeServices will be used and configured with a
JdbcTokenRepositoryImpl instance.
remember-me-parameter The name of the request parameter which toggles rememberme authentication. Defaults to "remember-me". Maps to the "parameter" property of
AbstractRememberMeServices.
4.0.2.RELEASE
Spring Security
206
remember-me-cookie The name of cookie which store the token for rememberme authentication. Defaults to "remember-me". Maps to the "cookieName" property of
AbstractRememberMeServices.
key Maps to the "key" property of AbstractRememberMeServices. Should be set to a unique value
18
to ensure that remember-me cookies are only valid within the one application . If this is not set a
secure random value will be generated. Since generating secure random values can take a while,
setting this value explicitly can help improve startup times when using the remember me functionality.
services-alias Exports the internally defined RememberMeServices as a bean alias, allowing it to
be used by other beans in the application context.
services-ref Allows complete control of the RememberMeServices implementation that will be used
by the filter. The value should be the id of a bean in the application context which implements this
interface. Should also implement LogoutHandler if a logout filter is in use.
token-repository-ref Configures a PersistentTokenBasedRememberMeServices but allows
the use of a custom PersistentTokenRepository bean.
token-validity-seconds
Maps
to
the
tokenValiditySeconds
property
of
AbstractRememberMeServices. Specifies the period in seconds for which the remember-me
cookie should be valid. By default it will be valid for 14 days.
use-secure-cookie It is recommended that remember-me cookies are only submitted over HTTPS
and thus should be flagged as "secure". By default, a secure cookie will be used if the connection
over which the login request is made is secure (as it should be). If you set this property to false,
secure cookies will not be used. Setting it to true will always set the secure flag on the cookie. This
attribute maps to the useSecureCookie property of AbstractRememberMeServices.
user-service-ref The remember-me services implementations require access to a
UserDetailsService, so there has to be one defined in the application context. If there is only
one, it will be selected and used automatically by the namespace configuration. If there are multiple
instances, you can specify a bean id explicitly using this attribute.
<request-cache> Element
Sets the RequestCache instance which will be used by the ExceptionTranslationFilter to store
request information before invoking an AuthenticationEntryPoint.
Parent Elements of <request-cache>
http
<request-cache> Attributes
ref Defines a reference to a Spring bean that is a RequestCache.
<session-management>
Session-management related functionality is
SessionManagementFilter to the filter stack.
implemented
by
the
addition
of
4.0.2.RELEASE
Spring Security
207
<session-management> Attributes
invalid-session-url Setting this attribute will inject the SessionManagementFilter with a
SimpleRedirectInvalidSessionStrategy configured with the attribute value. When an invalid
session ID is submitted, the strategy will be invoked, redirecting to the configured URL.
session-authentication-error-url Defines the URL of the error page which should be shown when
the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error code
will be returned to the client. Note that this attribute doesnt apply if the error occurs during a formbased login, where the URL for authentication failure will take precedence.
session-authentication-strategy-ref Allows injection of the SessionAuthenticationStrategy instance
used by the SessionManagementFilter
session-fixation-protection Indicates how session fixation protection will be applied when a user
authenticates. If set to "none", no protection will be applied. "newSession" will create a new
empty session, with only Spring Security-related attributes migrated. "migrateSession" will create
a new session and copy all session attributes to the new session. In Servlet 3.1 (Java EE 7)
and newer containers, specifying "changeSessionId" will keep the existing session and use the
container-supplied session fixation protection (HttpServletRequest#changeSessionId()). Defaults to
"changeSessionId" in Servlet 3.1 and newer containers, "migrateSession" in older containers. Throws
an exception if "changeSessionId" is used in older containers.
If session fixation protection is enabled, the SessionManagementFilter is injected with an
appropriately configured DefaultSessionAuthenticationStrategy. See the Javadoc for this
class for more details.
Child Elements of <session-management>
concurrency-control
<concurrency-control>
Adds support for concurrent session control, allowing limits to be placed on the number
of active sessions a user can have. A ConcurrentSessionFilter will be created,
and a ConcurrentSessionControlAuthenticationStrategy will be used with the
SessionManagementFilter. If a form-login element has been declared, the strategy object
will also be injected into the created authentication filter. An instance of SessionRegistry (a
SessionRegistryImpl instance unless the user wishes to use a custom bean) will be created for
use by the strategy.
Parent Elements of <concurrency-control>
session-management
<concurrency-control> Attributes
error-if-maximum-exceeded If set to "true" a SessionAuthenticationException will be raised
when a user attempts to exceed the maximum allowed number of sessions. The default behaviour
is to expire the original session.
expired-url The URL a user will be redirected to if they attempt to use a session which has been
"expired" by the concurrent session controller because the user has exceeded the number of allowed
sessions and has logged in again elsewhere. Should be set unless exception-if-maximum-
4.0.2.RELEASE
Spring Security
208
exceeded is set. If no value is supplied, an expiry message will just be written directly back to the
response.
max-sessions
Maps
to
the
maximumSessions
ConcurrentSessionControlAuthenticationStrategy.
property
of
session-registry-alias It can also be useful to have a reference to the internal session registry for
use in your own beans or an admin interface. You can expose the internal bean using the sessionregistry-alias attribute, giving it a name that you can use elsewhere in your configuration.
session-registry-ref The user can supply their own SessionRegistry implementation using the
session-registry-ref attribute. The other concurrent session control beans will be wired up to
use it.
<x509>
Adds support for X.509 authentication. An X509AuthenticationFilter will be added to the stack
and an Http403ForbiddenEntryPoint bean will be created. The latter will only be used if no other
authentication mechanisms are in use (its only functionality is to return an HTTP 403 error code). A
PreAuthenticatedAuthenticationProvider will also be created which delegates the loading of
user authorities to a UserDetailsService.
Parent Elements of <x509>
http
<x509> Attributes
authentication-details-source-ref A reference to an AuthenticationDetailsSource
subject-principal-regex Defines a regular expression which will be used to extract the username
from the certificate (for use with the UserDetailsService).
user-service-ref Allows a specific UserDetailsService to be used with X.509 in the case where
multiple instances are configured. If not set, an attempt will be made to locate a suitable instance
automatically and use that.
<filter-chain-map>
Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
<filter-chain-map> Attributes
request-matcher Defines the strategy use for matching incoming requests. Currently the options are
'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular
expressions.
Child Elements of <filter-chain-map>
filter-chain
<filter-chain>
Used within to define a specific URL pattern and the list of filters which apply to the URLs matching
that pattern. When multiple filter-chain elements are assembled in a list in order to configure a
4.0.2.RELEASE
Spring Security
209
FilterChainProxy, the most specific patterns must be placed at the top of the list, with most general ones
at the bottom.
Parent Elements of <filter-chain>
filter-chain-map
<filter-chain> Attributes
filters A comma separated list of references to Spring beans that implement Filter. The value
"none" means that no Filters should be used for this `FilterChain.
pattern A-pattern that creates RequestMatcher in combination with the request-matcher
request-matcher-ref A reference to a RequestMatcher that will be used to determine if the
Filters from the `filters attribute should be invoked.
<filter-security-metadata-source>
Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor.
Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the<http>
element. The intercept-url elements used should only contain pattern, method and access attributes.
Any others will result in a configuration error.
<filter-security-metadata-source> Attributes
id A bean identifier, used for referring to the bean elsewhere in the context.
lowercase-comparisons Compare after forcing to lower case
request-matcher Defines the strategy use for matching incoming requests. Currently the options are
'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular
expressions.
use-expressions Enables the use of expressions in the 'access' attributes in <intercept-url> elements
rather than the traditional list of configuration attributes. Defaults to 'true'. If enabled, each attribute
should contain a single boolean expression. If the expression evaluates to 'true', access will be
granted.
Child Elements of <filter-security-metadata-source>
intercept-url
<websocket-message-broker>
The websocket-message-broker element has two different modes. If the websocket-messagebroker@id is not specified, then it will do the following things:
Ensure
that
any
SimpAnnotationMethodMessageHandler
has
the
AuthenticationPrincipalArgumentResolver registered as a custom argument resolver. This allows the
use of @AuthenticationPrincipal to resolve the principal of the current Authentication
4.0.2.RELEASE
Spring Security
210
<intercept-message>
Defines an authorization rule for a message.
Parent Elements of <intercept-message>
websocket-message-broker
<intercept-message> Attributes
pattern An ant based pattern that matches on the Message destination. For example, "/" matches
any Message with a destination; "/admin/" matches any Message that has a destination that starts
with "/admin/**".
type The type of message to match on. Valid values are defined in SimpMessageType
(i.e. CONNECT, CONNECT_ACK, HEARTBEAT, MESSAGE, SUBSCRIBE, UNSUBSCRIBE,
DISCONNECT, DISCONNECT_ACK, OTHER).
access The expression used to secure the Message. For example, "denyAll" will deny access
to all of the matching Messages; "permitAll" will grant access to all of the matching Messages;
4.0.2.RELEASE
Spring Security
211
"hasRole('ADMIN') requires the current user to have the role 'ROLE_ADMIN' for the matching
Messages.
<authentication-manager>
Every Spring Security application which uses the namespace must have include this element
somewhere. It is responsible for registering the AuthenticationManager which provides
authentication services to the application. All elements which create AuthenticationProvider
instances should be children of this element.
<authentication-manager> Attributes
alias This attribute allows you to define an alias name for the internal instance for use in your own
configuration. Its use is described in thenamespace introduction.
erase-credentials If set to true, the AuthenticationManger will attempt to clear any credentials
data in the returned Authentication object, once the user has been authenticated. Literally it maps
to the eraseCredentialsAfterAuthentication property of the ProviderManager. This is
discussed in the Core Services chapter.
id This attribute allows you to define an id for the internal instance for use in your own configuration.
It is the same a the alias element, but provides a more consistent experience with elements that use
the id attribute.
Child Elements of <authentication-manager>
authentication-provider
ldap-authentication-provider
<authentication-provider>
Unless used with a ref attribute, this element is shorthand for configuring a DaoAuthenticationProvider.
DaoAuthenticationProvider loads user information from a UserDetailsService and
compares the username/password combination with the values supplied at login. The
UserDetailsService instance can be defined either by using an available namespace element
( jdbc-user-service or by using the user-service-ref attribute to point to a bean defined
elsewhere in the application context). You can find examples of these variations in the namespace
introduction.
Parent Elements of <authentication-provider>
authentication-manager
4.0.2.RELEASE
Spring Security
212
<authentication-provider> Attributes
ref Defines a reference to a Spring bean that implements `AuthenticationProvider `.
If you have written your own AuthenticationProvider implementation (or want to configure one
of Spring Securitys own implementations as a traditional bean for some reason, then you can use the
following syntax to add it to the internal `ProviderManagers list:
<security:authentication-manager>
<security:authentication-provider ref="myAuthenticationProvider" />
</security:authentication-manager>
<bean id="myAuthenticationProvider" class="com.something.MyAuthenticationProvider"/>
<jdbc-user-service>
Causes creation of a JDBC-based UserDetailsService.
<jdbc-user-service> Attributes
authorities-by-username-query An SQL statement to query for a users granted authorities given
a username.
The default is
select username, authority from authorities where username = ?
id A bean identifier, used for referring to the bean elsewhere in the context.
role-prefix A non-empty string prefix that will be added to role strings loaded from persistent storage
(default is "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
users-by-username-query An SQL statement to query a username, password, and enabled status
given a username. The default is
4.0.2.RELEASE
Spring Security
213
<password-encoder>
Authentication providers can optionally be configured to use a password encoder as described
in the namespace introduction. This will result in the bean being injected with the appropriate
PasswordEncoder instance, potentially with an accompanying SaltSource bean to provide salt
values for hashing.
Parent Elements of <password-encoder>
authentication-provider
password-compare
<password-encoder> Attributes
base64 Whether a string should be base64 encoded
hash Defines the hashing algorithm used on user passwords. We recommend strongly against using
MD4, as it is a very weak hashing algorithm.
ref Defines a reference to a Spring bean that implements `PasswordEncoder `.
Child Elements of <password-encoder>
salt-source
<salt-source>
Password salting strategy. A system-wide constant or a property from the UserDetails object can be
used.
Parent Elements of <salt-source>
password-encoder
<salt-source> Attributes
ref Defines a reference to a Spring bean Id.
system-wide A single value that will be used as the salt for a password encoder.
user-property A property of the UserDetails object which will be used as salt by a password encoder.
Typically something like "username" might be used.
<user-service>
Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.
Usernames are converted to lower-case internally to allow for case-insensitive lookups, so this should
not be used if case-sensitivity is required.
<user-service> Attributes
id A bean identifier, used for referring to the bean elsewhere in the context.
4.0.2.RELEASE
Spring Security
214
properties The location of a Properties file where each line is in the format of
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
<user>
Represents a user in the application.
Parent Elements of <user>
user-service
<user> Attributes
authorities One of more authorities granted to the user. Separate authorities with a comma (but no
space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
disabled Can be set to "true" to mark an account as disabled and unusable.
locked Can be set to "true" to mark an account as locked and unusable.
name The username assigned to the user.
password The password assigned to the user. This may be hashed if the corresponding
authentication provider supports hashing (remember to set the "hash" attribute of the "user-service"
element). This attribute be omitted in the case where the data will not be used for authentication, but
only for accessing authorities. If omitted, the namespace will generate a random value, preventing its
accidental use for authentication. Cannot be empty.
4.0.2.RELEASE
Spring Security
215
<after-invocation-provider>
This element can be used to decorate an AfterInvocationProvider for use by the security
interceptor maintained by the <global-method-security> namespace. You can define zero or
more of these within the global-method-security element, each with a ref attribute pointing to
an AfterInvocationProvider bean instance within your application context.
Parent Elements of <after-invocation-provider>
global-method-security
<after-invocation-provider> Attributes
ref Defines a reference to a Spring bean that implements ` AfterInvocationProvider`.
<pre-post-annotation-handling>
Allows the default expression-based mechanism for handling Spring Securitys pre and post invocation
annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only
applies if these annotations are enabled.
4.0.2.RELEASE
Spring Security
216
<invocation-attribute-factory>
Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post
invocation metadata from the annotated methods.
Parent Elements of <invocation-attribute-factory>
pre-post-annotation-handling
<invocation-attribute-factory> Attributes
ref Defines a reference to a Spring bean Id.
<post-invocation-advice>
Customizes
the
PostInvocationAdviceProvider
with
the
ref
as
PostInvocationAuthorizationAdvice for the <pre-post-annotation-handling> element.
the
<pre-invocation-advice>
Customizes the PreInvocationAuthorizationAdviceVoter with the ref as the
PreInvocationAuthorizationAdviceVoter for the <pre-post-annotation-handling> element.
Parent Elements of <pre-invocation-advice>
pre-post-annotation-handling
<pre-invocation-advice> Attributes
ref Defines a reference to a Spring bean Id.
4.0.2.RELEASE
Spring Security
217
methods and interfaces in your service layer using the <protect-pointcut> element. You can find
an example in the namespace introduction.
Parent Elements of <protect-pointcut>
global-method-security
<protect-pointcut> Attributes
access Access configuration attributes list that applies to all methods matching the pointcut, e.g.
"ROLE_A,ROLE_B"
expression An AspectJ expression, including the 'execution' keyword. For example, 'execution(int
com.foo.TargetObject.countLength(String))' (without the quotes).
<intercept-methods>
Can be used inside a bean definition to add a security interceptor to the bean and set up access
configuration attributes for the beans methods
<intercept-methods> Attributes
access-decision-manager-ref Optional AccessDecisionManager bean ID to be used by the created
method security interceptor.
Child Elements of <intercept-methods>
protect
<method-security-metadata-source>
Creates a MethodSecurityMetadataSource instance
<method-security-metadata-source> Attributes
id A bean identifier, used for referring to the bean elsewhere in the context.
use-expressions Enables the use of expressions in the 'access' attributes in <intercept-url> elements
rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute
should contain a single boolean expression. If the expression evaluates to 'true', access will be
granted.
Child Elements of <method-security-metadata-source>
protect
<protect>
Defines a protected method and the access control configuration attributes that apply to it. We strongly
advise you NOT to mix "protect" declarations with any services provided "global-method-security".
Parent Elements of <protect>
intercept-methods
method-security-metadata-source
4.0.2.RELEASE
Spring Security
218
<protect> Attributes
access Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".
method A method name
<ldap-authentication-provider>
This element is shorthand for the creation of an LdapAuthenticationProvider
instance. By default this will be configured with a BindAuthenticator instance and a
DefaultAuthoritiesPopulator. As with all namespace authentication providers, it must be
included as a child of the authentication-provider element.
4.0.2.RELEASE
Spring Security
219
4.0.2.RELEASE
Spring Security
220
an alternative, then the default search values of user-search-filter="(uid={0})" and usersearch-base="" will be used.
Child Elements of <ldap-authentication-provider>
password-compare
<password-compare>
This is used as child element to <ldap-provider> and switches the authentication strategy from
BindAuthenticator to PasswordComparisonAuthenticator.
Parent Elements of <password-compare>
ldap-authentication-provider
<password-compare> Attributes
hash Defines the hashing algorithm used on user passwords. We recommend strongly against using
MD4, as it is a very weak hashing algorithm.
password-attribute The attribute in the directory which contains the user password. Defaults to
"userPassword".
Child Elements of <password-compare>
password-encoder
<ldap-user-service>
This element configures an LDAP UserDetailsService. The class used is
LdapUserDetailsService which is a combination of a FilterBasedLdapUserSearch and a
DefaultLdapAuthoritiesPopulator. The attributes it supports have the same usage as in
<ldap-provider>.
<ldap-user-service> Attributes
cache-ref Defines a reference to a cache for use with a UserDetailsService.
group-role-attribute The LDAP attribute name which contains the role name which will be used within
Spring Security. Defaults to "cn".
group-search-base Search base for group membership searches. Defaults to "" (searching from the
root).
group-search-filter Group search filter. Defaults to (uniqueMember={0}). The substituted parameter
is the DN of the user.
id A bean identifier, used for referring to the bean elsewhere in the context.
role-prefix A non-empty string prefix that will be added to role strings loaded from persistent storage
(e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
server-ref The optional server to use. If omitted, and a default LDAP server is registered (using <ldapserver> with no Id), that server will be used.
4.0.2.RELEASE
Spring Security
221
4.0.2.RELEASE
Spring Security
222
39.1 spring-security-core
The core module must be included in any project using Spring Security.
Table 39.1. Core Depenendencies
Dependency
Version
Description
aopalliance
1.0
ehcache
1.6.2
spring-aop
spring-beans
spring-expression
spring-jdbc
spring-tx
aspectjrt
1.6.10
jsr250-api
1.0
4.0.2.RELEASE
Spring Security
223
39.2 spring-security-remoting
This module is typically required in web applications which use the Servlet API.
Table 39.2. Remoting Dependencies
Dependency
Version
Description
spring-security-core
spring-web
39.3 spring-security-web
This module is typically required in web applications which use the Servlet API.
Table 39.3. Web Dependencies
Dependency
Version
Description
spring-security-core
spring-web
spring-jdbc
spring-tx
Required by remember-me
persistent token repository
implementations (optional).
39.4 spring-security-ldap
This module is only required if you are using LDAP authentication.
Table 39.4. LDAP Dependencies
Dependency
Version
Description
1.3.0
spring-security-core
spring-ldap-core
spring-tx
apache-ds
4.0.2.RELEASE
1.5.5
Spring Security
224
Dependency
Version
Description
shared-ldap
0.9.15
ldapsdk
4.1
39.5 spring-security-config
This module is required if you are using Spring Security namespace configuration.
Table 39.5. Config Dependencies
Dependency
Version
Description
spring-security-core
spring-security-web
spring-security-ldap
spring-security-openid
aspectjweaver
1.6.10
39.6 spring-security-acl
The ACL module.
Table 39.6. ACL Dependencies
Dependency
Version
Description
1.6.2
spring-security-core
ehcache
4.0.2.RELEASE
Spring Security
225
Dependency
Version
Description
spring-jdbc
spring-tx
39.7 spring-security-cas
The CAS module provides integration with JA-SIG CAS.
Table 39.7. CAS Dependencies
Dependency
Version
Description
cas-client-core
3.1.12
ehcache
1.6.2
spring-security-core
spring-security-web
39.8 spring-security-openid
The OpenID module.
Table 39.8. OpenID Dependencies
Dependency
Version
Description
openid4java-nodeps
0.9.6
httpclient
4.1.1
openid4java-nodeps depends
on HttpClient 4.
guice
2.0
openid4java-nodeps depends
on Guice 2.
spring-security-core
spring-security-web
39.9 spring-security-taglibs
Provides Spring Securitys JSP tag implementations.
4.0.2.RELEASE
Spring Security
226
Version
Description
spring-security-core
spring-security-web
spring-security-acl
spring-expression
4.0.2.RELEASE
Spring Security
227