Jul 07
5 Minute Guide to Spring Security
Although I’ve used Acegi Security in the past, I hadn’t tried it since it was renamed Spring Security and folded into the Spring Portfolio. I decided to approach its integration into a typical Spring web application with the eyes of a new user and write up my notes as a 5 minute guide to Spring Security.
Pretending to be a new user, I found the suggested steps a bit bewildering. Let’s take these one at a time, and I’ll try to help you out where the instructions are unclear:
1. First of all, deploy the “Tutorial Sample”, which is included in the main distribution ZIP file.
Aside from the weird packaging of Spring Security, it’s not clear which file this is. You should be deploying spring-security-samples-tutorial-2.0.x.war to your servlet container in the usual fashion. In the case of Tomcat, for example, use the deployment tool or drop this into your webapps directory. You should see the tutorial application in your browser. Let’s move to step 2…
2. Next, follow the Petclinic Tutorial , which covers how to add Spring Security to the commonly-used Petclinic sample application that ships with Spring.
This is pretty straightforward. The only error I found was that there is a reference to %spring-sec-tutorial%\WEB-INF\applicationContext-security-ns.xml. This should be applicationContext-security.xml instead. Note that I didn’t actually try this part of the tutorial with the Petclinic application, since I had my own test app I wanted to integrate with.
And here’s where the fun starts. Once you get past the convention over configuration convenience, you will need to customize Spring Security. One of the first things I looked for in the documentation was what all the bits in the XML namespace did. When this product was Acegi security, you could be pretty sure of looking at the Javadoc and getting documentation. Not so with XML configuration! While the Spring Framework documentation includes an excellent appendix with a reasonable level of detail on each of the namespaced XML declarations, Spring Security has nothing like this.
With convention over configuration, good documentation of the defaults becomes especially important, and it’s unfortunate the documentation isn’t really adequate in this area.
That said, I’ll try to cover a basic scenario here where we integrate Spring Security, using database-backed authentication, into an existing Spring web application. Here’s what I wanted for my example:
- Database-backed authentication
- Users have a single “role” - either plain user, or admin
- Customized login page
It’s a bit hard to cover this in 5 minutes, so I have skipped some of the stuff I hope you know already, such as use of Spring XML namespaces, and configuring simple JDBC DataSources. Please let me know if you miss this stuff!
Getting Started
I would suggest getting started with the applicationContext-security.xml that is found in the tutorial sample, and trimming it down a bit. Here’s what I got when I trimmed it down:
<?xml version="1.0" encoding="UTF-8"?> <!-- - Sample namespace-based configuration - - $Id: applicationContext-security.xml 3019 2008-05-01 17:51:48Z luke_t $ --> <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-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"> <global-method-security secured-annotations="enabled"> </global-method-security> <http auto-config="true"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> </http> <!-- Usernames/Passwords are rod/koala dianne/emu scott/wombat peter/opal --> <authentication-provider> <password-encoder hash="md5"/> <user-service> <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" /> <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" /> <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" /> <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" /> </user-service> </authentication-provider> </beans:beans>
This makes a good baseline for the modifications we’re going to make. But first…
Mapping XML Elements to Java Code
I found it very helpful at this point, before messing with the XML, to know where the Java code was that corresponded to the available XML elements. The basic class that Spring Security uses for mapping XML elements to beans is SecurityNamespaceHandler. The code in this class simply delegates XML elements to bean definition parsers. It’s easy to follow along and map XML elements to Java code in this way. Unfortunately, don’t expect extensive commenting in the Java code to help you
web.xml Changes
I agree with the Spring Security documentation and found it easier to extract the security-related stuff into its own XML configuration file. This allows you to play XML tricks and not require namespace-tagging for the security elements. First off, you have to include a reference to applicationContext-security.xml in your [Spring] initialization parameters in your web.xml file:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-app-servlet.xml /WEB-INF/applicationContext-security.xml </param-value> </context-param>
Next, as instructed by the Spring Security getting started guide, you need to add the filter mapping. In my case, this went right after the <context-param> end tag, since I didn’t have any other filters:
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
This default mapping will run all requests to your application through Spring Security. Now we’re done with web.xml, and we move on to…
Database-Backed Authentication
In my case, my application was already configured to use a JDBC DataSource, so pointing Spring Security at my JDBC data source was as easy as modifying the authentication-provider element to reference my already configured Spring bean:
<authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider>
Now, the immediate question I asked is - OK, what does the convention over configuration assume my database tables look like? If you look at the documentation of the JDBC authentication provider, you would expect to see that information there, but you’d be wrong.
Instead, you have to look at the SQL queries that are hard-coded in the JdbcDaoImpl class and infer the schema structure for yourself. This article has a graphical depiction of the basic schema down in section 5.4.
If you want to configure the queries that are used, simply match the available attributes on the jdbc-user-service element to the SQL queries in the Java class I referenced above. In my example, I wanted to simplify my schema by adding the user’s role directly to the user table. So I modified the XML configuration slightly as follows:
<jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="select username,authority from users where username=?"/>This allowed me to put values in the ‘authority’ column like ‘ROLE_ADMIN’ or ‘ROLE_USER’, which translate directly into Spring Security roles!
Configuring URL authorization
Mapping URLs to roles is really easy. In your http element, simply put successive elements like this:
<intercept-url pattern="/admin/*.do" access="ROLE_ADMIN" /> <intercept-url pattern="/**.do" access="ROLE_USER,ROLE_ADMIN" />
Note here that the ‘access’ attribute values directly correspond to the values returned by the second column of the authorities-by-username-query. The ‘.do’ mapping is what I arbitrarily chose for my application - you may have to adjust depending on what your application’s Spring-managed URLs look like.
Configuring and Branding Spring Security-managed Pages
Finally, I wanted to figure out where the pages related to Spring Security should be configured, so that I could modify them if I needed to. Somewhat oddly, Spring Security ships with a default login page whose HTML markup is located in a class file - DefaultLoginPageGeneratingFilter. We would (obviously) like to replace this with our own custom page. Since we are authenticating everything passing through the Spring servlet, we must use a JSP for this.
Add the following to the http tag in the security configuration file:
<form-login login-page="/login.jsp" />Now you need to put the login.jsp page in your web application (generally in the WEB-INF directory). The basic structure of the page you’re creating will look like this:
<%@ page import="org.springframework.security.ui.webapp.AuthenticationProcessingFilter" %> <%@ page import="org.springframework.security.ui.AbstractProcessingFilter" %> <%@ page import="org.springframework.security.AuthenticationException" %> ... <form action="j_spring_security_check"> <label for="j_username">Username</label> <input type="text" name="j_username" id="j_username" <c:if test="${not empty param.login_error}">value='<%= session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>'</c:if>/> <br/> <label for="j_password">Password</label> <input type="password" name="j_password" id="j_password"/> <br/> <input type='checkbox' name='_spring_security_remember_me'/> Remember me on this computer. <br/> <input type="submit" value="Login"/> </form>
The names of the form elements and form action must match what is shown here otherwise your login form will not work!
Note also that this is a plain ol’ JSP page, and not under Spring control. It is likely that you could play with the servlet filter patterns in web.xml to bring these pages under Spring control, but that is a topic outside the scope of this brief tutorial.
There are a couple other pages you will want to configure.
Access Denied: This is the page the user will see if they are denied access to the site due to lack of authorization (i.e. tried to hit a page that they didn’t have access to hit, even though they were authenticated properly). This is configured as follows:
<http ... access-denied-page="/accessDenied.jsp"> ... </http>
Default Target URL: This is where the user will be redirected upon successful login. This can (and probably should) be a page located under Spring control. Configured as follows:
<http ... > ... <form-login ... default-target-url="/home.do"/> ... </http>
Logout URL: The page where the user is redirected upon a successful logout. This can be a page located under Spring control too (provided that it allows anonymous access):
<http ... > ... <logout logout-success-url="/home.do"/> ... </http>
Login Failure URL: Where the user will be sent if there was an authentication failure. Typically this is back to the login form, with a URL parameter, such as:
<http ... > ... <form-login ... authentication-failure-url="/login.jsp?login_error=1"/> ... </http>
Putting it Together
Here’s what my whole sample Spring security configuration looked like when I was done:
<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-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"> <global-method-security secured-annotations="enabled"> <!-- AspectJ pointcut expression that locates our "post" method and applies security that way <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/> --> </global-method-security> <http auto-config="true" access-denied-page="/accessDenied.jsp"> <intercept-url pattern="/login.jsp*" filters="none"/> <intercept-url pattern="/admin/editUser.do" access="ROLE_ADMIN" /> <intercept-url pattern="/admin/searchUsers.do" access="ROLE_ADMIN" /> <intercept-url pattern="/**.do" access="ROLE_USER,ROLE_ADMIN" /> <form-login authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home.do"/> <logout logout-success-url="/home.do"/> </http> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" authorities-by-username-query="select username,authority from users where username=?"/> </authentication-provider> </beans:beans>
Wrap-Up
Ironically, just as I was drafting this article, a smart colleague of mine happened to come to me telling me about all the problems he was having getting started with Spring Security. He complained about the lack of detailed documentation on the XML, and the fact that the getting started documentation really wasn’t comprehensive (both complains that I had as well). Note that this colleague also happened to be responsible for implementing Acegi Security with Spring in a prior project that we worked on together - so he was intimately familiar with the underlying technology. He ended up going back to the Java-based configuration mechanism in frustration!
Hope this helps you out and I always appreciate hearing your comments and questions.
Related Articles
- Juggling Java has a very brief article on customizing Spring Security.
- Bart van Riel has a great tutorial on Acegi Security, which has some relevant bits around the database schema that you might find interesting.


July 8th, 2008 at 11:53 pm
[…] It’s Only Software » 5 Minute Guide to Spring Security […]
July 10th, 2008 at 7:59 am
Awesome article, I am new to Spring Security and I have heard great things about it. I plan on using this as a useful reference for the future.
Thank you for the concrete example!
July 11th, 2008 at 11:18 am
Terrific, useful, concise. Where was this article a month ago when I REALLY needed it!
Thanks for the great article, Peter!
July 13th, 2008 at 2:44 am
Great article. My general configuration was fine, but I was having trouble with the specific details of the http XML configuration. This was a big help since the Spring documentation doesn’t say much and the distributed tutorials don’t really customize those specific attributes.
For you Struts 2 users out there (and to anyone else to whom this might apply), the above login.jsp snippet didn’t fully work because the session variable was accessed differently for me. Here’s what that became for me:
Thanks again for the help!
Cheers
July 14th, 2008 at 7:30 pm
Really nice tutorial, thanks for such a work!
It has been successfull for me!
Thanks!
July 14th, 2008 at 7:44 pm
Thanks for the feedback, everyone! Glad to see it helped some folks.
July 16th, 2008 at 7:31 pm
Way to go! This article helped me alot!!! That part is missing in the Spring documentation. THANKS!!!
July 17th, 2008 at 11:26 am
Its excellent article. If anyone wants to apply Single Session Control to logged in user do the following steps.
1) in web.xml add a listner.
2)In Spring security configuration
July 25th, 2008 at 11:00 am
[…] - bookmarked by 3 members originally found by p4style on July 14, 2008 5 Minute Guide to Spring Security http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/ - bookmarked by 4 […]