Spring Security Java Config Preview: Web Security
Update
Users should refer to the Spring Security Reference which contains more up to date information.
Original Blog Post
In my previous post , I introduced Spring Security Java configuration and discussed some of the logistics of the project. In this post, we will start off by walking through a very simple web security configuration. We will then spice things up a bit with configuration that has been customized some.
Hello Web Security
In this section we go through the most basic configuration for web based security. It can be broken into four steps:
WebSecurityConfigurerAdapter
The
@EnableWebSecurity
annotation and
WebSecurityConfigurerAdapter
work together to provide web based security. By extending
WebSecurityConfigurerAdapter
and only a few lines of code we are able to do the following:
For your reference, this is similar to the following XML configuration with a few exceptions:
AbstractAnnotationConfigDispatcherServletInitializer
The next step is to ensure that the root
ApplicationContext
includes the
HelloWebSecurityConfiguration we just specified
. There are
many different ways
we could do this, but if you are using Spring's
AbstractAnnotationConfigDispatcherServletInitializer
it might look something like this:
To put this in perspective, Spring Security was traditionally initialized using something similar to the following lines within the web.xml:
<!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- Load all Spring XML configuration including our security.xml file --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/*.xml</param-value> </context-param>[callout title="Ordering of WebApplicationInitializer"] If any servlet Filter mappings are added after AbstractSecurityWebApplicationInitializer is invoked, they might be accidentally added before springSecurityFilterChain. Unless an application contains Filter instances that do not need to be secured, springSecurityFilterChain should be before any other Filter mappings. The @Order annotation can be used to help ensure that any WebApplicationInitializer is loaded in a deterministic order.[/callout]
AbstractSecurity WebApplicationInitializer
The last step is we need to map the
springSecurityFilterChain
. We can easily do this by extending
AbstractSecurityWebApplicationInitializer
and optionally overriding methods to customize the mapping.
The most basic example below accepts the default mapping and adds springSecurityFilterChain with the following characteristics:
ERROR
and
REQUEST
springSecurityFilterChain
mapping is inserted before any servlet Filter mappings that have already been configured
The above code is the equivalent of the following lines within the web.xml:
<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> <dispatcher>ERROR</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping>CustomWebSecurityConfigurerAdapter
Our HelloWebSecurityConfiguration sample, demonstrates that Spring Security Java configuration can provide some very nice defaults for us. Let's take a look at some basic customization.
@EnableWebSecurity @Configuration public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { .inMemoryAuthentication() .withUser("user") // #1 .password("password") .roles("USER") .and() .withUser("admin") // #2 .password("password") .roles("ADMIN","USER"); @Override public void configure(WebSecurity web) throws Exception { .ignoring() .antMatchers("/resources/**"); // #3 @Override protected void configure(HttpSecurity http) throws Exception { .authorizeUrls() .antMatchers("/signup","/about").permitAll() // #4 .antMatchers("/admin/**").hasRole("ADMIN") // #6 .anyRequest().authenticated() // 7 .and() .formLogin() // #8 .loginUrl("/login") // #9 .permitAll(); // #5Assuming that we adjust AbstractAnnotationConfigDispatcherServletInitializer to load our new configuration, our CustomWebSecurityConfigurerAdapter will do the following:
For those that are familiar with the XML based configuration, the configuration above is very similar to the following XML configuration:
<http security="none" pattern="/resources/**"/> <http use-expressions="true"> <intercept-url pattern="/logout" access="permitAll"/> <intercept-url pattern="/login" access="permitAll"/> <intercept-url pattern="/signup" access="permitAll"/> <intercept-url pattern="/about" access="permitAll"/> <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/> <logout logout-success-url="/login?logout" logout-url="/logout" <form-login authentication-failure-url="/login?error" login-page="/login" login-processing-url="/login" password-parameter="password" username-parameter="username" </http> <authentication-manager> <authentication-provider> <user-service> <user name="user" password="password" authorities="ROLE_USER"/> <user name="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/> </user-service> </authentication-provider> </authentication-manager>Similarities to the XML Namespace
After looking at our slightly more complicated example, you might be able to find some similarities between the XML namespace and the Java configuration. Here are some of the more useful points:
Differences to the XML Namespace
You will notice that there are some important differences between the XML and Java configuration too.
Additional Web Samples
Sample Compatibility Since the code was merged into Spring Security 3.2 M2 with no changes, the samples will be compatible with either the stand alone module or spring-security-config-3.2.0.M2+
We have given a few examples of how the Spring Security Java configuration can be used to secure your web application in order to wet your appetite. Below you can find a number of resources with additional samples.
XML namespace to Java Config
If you are having trouble converting from the XML namespace to the Java configuration, you can refer to the tests. The convention is that the test for a given XML element will start with "Namespace", contain the XML element name, and end with "Tests". For example, to learn how the http element maps to Java configuration, you would refer to the NamespaceHttpTests . Another example, is that you can figure out how the remember-me namespace maps to Java configuration in the NamespaceRememberMeTests .