原文地址:【1】https://spring.io/blog/2013/07/02/spring-security-java-config-preview-introduction/
【2】https://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/
【3】https://spring.io/blog/2013/07/04/spring-security-java-config-preview-method-security/
【4】https://spring.io/blog/2013/07/05/spring-security-java-config-preview-oauth/
【5】https://spring.io/blog/2013/07/11/spring-security-java-config-preview-readability/
Spring Security Java Config Preview: Introduction
Yesterday I announced the release of Spring Security Java Configuration support and the release of Spring Security 3.2.0.M2 which contains Java Configuration support.
Spring Security's Java Configuration support is intended to provide a complete replacement of the XML namespace configuration. It is also designed to be extensible, so that Spring Security's extension projects can work nicely with the Java Configuration support.
In this first post of a five part Spring Security Java Configuration blog series, I discuss the logistics of the Spring Security Java Configuration project.
Availability
Before we get started, I’d like to talk about the two modules that Spring Security’s Java Configuration can be found.
Availability in Spring Security 3.2.0.M2+
Spring Security Java Configuration has been copied into the Spring Security 3.2.0.M2+ code base. This means if you are using Spring Security 3.2.0.M2+ you should ensure to have the spring-security-config jar on your classpath. For example, you might have the following entries in your Maven pom.xml:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.0.M2</version>
</dependency>
…
<repository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>
Availability for Spring Security 3.1.4.RELEASE+
In order to encourage users to try Spring Security Java Configuration, it is also available as a standalone module called spring-security-javaconfig. For example, you might have the following entries in your Maven pom.xml:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-javaconfig</artifactId>
<version>1.0.0.M1</version>
</dependency>
…
<repository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>
00 with the Early discount!
Feedback Please
If you encounter a bug, have an idea for improvement, etc please do not hesitate to bring it up! We want to hear your thoughts so we can ensure we get it right before the code is generally available. Trying out new features early is a good and simple way to give back to the community. This also ensures that the features you want are present and working as you think they should.
Please log any issues or feature requests to the Spring Security JIRA under the category "Java Config". After logging a JIRA, we encourage (but do not require) you to submit your changes in a pull request. You can read more about how to do this in the Contributor Guidelines
If you have questions on how to do something, please use the Spring Security forums or Stack Overflow with the tag spring-security (I will be monitoring them closely). If you have specific comments questions about this blog, feel free to leave a comment. Using the appropriate tools will help make it easier for everyone.
Conclusion
You should now have a clear idea of why Spring Security Java Configuration exists it multiple places, where you will find updates, and where to log issues to. In the next post, we will walk through using Spring Security Java configuration in a web application.
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:
- Updating your dependencies - we demonstrated this using Maven in our previous blog post
- Provide the Spring Security configuration - in our example this is done with a WebSecurityConfigurerAdapter
- Ensure the Spring Security configuration is loaded - in our example this is done with AbstractAnnotationConfigDispatcherServletInitializer
- Configure the springSecurityFilterChain - in our example this is done with AbstractSecurityWebApplicationInitializer
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:
- Require the user to be authenticated prior to accessing any URL within our application
- Create a user with the username “user”, password “password”, and role of “ROLE_USER”
- Enables HTTP Basic and Form based authentication
- Spring Security will automatically render a login page and logout success page for you
@Configuration
@EnableWebSecurity
public class HelloWebSecurityConfiguration
extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
For your reference, this is similar to the following XML configuration with a few exceptions:
- Spring Security will render the login, authentication failure url, and logout success URLs
- The login-processing-url will only be processed for HTTP POST
- The login-page will only be processed for HTTP GET
<http use-expressions="true">
<intercept-url pattern="/**" access="authenticated"/>
<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-service>
</authentication-provider>
</authentication-manager>
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:
public class SpringWebMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { HelloWebSecurityConfiguration.class };
}
...
}
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>
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:
- springSecurityFilterChain is mapped to “/*”
- springSecurityFilterChain uses the dispatch types of
ERROR
andREQUEST
- The
springSecurityFilterChain
mapping is inserted before any servlet Filter mappings that have already been configured
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
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) {
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 {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.antMatchers("/signup","/about").permitAll() // #4
.antMatchers("/admin/**").hasRole("ADMIN") // #6
.anyRequest().authenticated() // 7
.and()
.formLogin() // #8
.loginUrl("/login") // #9
.permitAll(); // #5
}
}
Assuming that we adjust AbstractAnnotationConfigDispatcherServletInitializer to load our new configuration, our CustomWebSecurityConfigurerAdapter will do the following:
- Allow in memory authentication with a user named “user”
- Allow in memory authentication with an administrative user named “admin”
- Ignore any request that starts with “/resources/”. This is similar to configuring http@security=none when using the XML namespace configuration.
- Allow anyone (including unauthenticated users) to access to the URLs “/signup” and “/about”
- Allow anyone (including unauthenticated users) to access to the URLs “/login” and “/login?error”. The permitAll() in this case means, allow access to any URL that formLogin() uses.
- Any URL that starts with “/admin/” must be an administrative user. For our example, that would be the user “admin”.
- All remaining URLs require that the user be successfully authenticated
- Setup form based authentication using the Java configuration defaults. Authentication is performed when a POST is submitted to the URL “/login” with the parameters “username” and “password”.
- Explicitly state the login page, which means the developer is required to render the login page when GET /login is requested.
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:
- HttpSecurity is quite similar to the http namespace element. It allows configuring web based security for a certain selection (in this case all) requests.
- WebSecurity is quite similar to any Security namespace elements that are for the web and that do not require a parent (i.e. security=none, debug, etc). It allows configuring things that impact all of web security.
- WebSecurityConfigurerAdapter is a convenience class that allows customization to both WebSecurity and HttpSecurity. We can extend WebSecurityConfigurerAdapter multiple times (in distinct objects) to replicate the behavior of having multiple http elements.
- By formatting our Java configuration code it is much easier to read. It can be read similar to the XML namespace equivalent where “and()” represents optionally closing an XML element.
Differences to the XML Namespace
You will notice that there are some important differences between the XML and Java configuration too.
- When creating our users in #1 and #2, we do not specify “ROLE_” as we would with the XML configuration. Since this convention is so common, the “roles” method automatically adds “ROLE_” for you. If you did not want “ROLE_” added you could use the authorities method instead.
- 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:
- GET /login renders the login page instead of /spring_security_login
- POST /login authenticates the user instead of /j_spring_security_check
- The username parameter defaults to username instead of j_username
- The password parameter defaults to password instead of j_password
- Java configuration can easily map multiple request matchers to the same roles. This is apparent in #4 where we map two URLs to be accessible to anyone
- Java configuration tries to remove redundant code. For example, instead of repeating our /login URL in the form-login element and the intercept-url element as we did with the XML, we can simply declare that users should have access to any URL related to formLogin() as shown with #5
- When mapping HTTP requests using the hasRole method as we did in #6, we do not need to specify “ROLE_” as we would in XML. Again, this is so common of a convention that the hasRole method automatically adds “ROLE_” for you. If you did not want to automatically prefix with “ROLE_”, you could use the “access” method.
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.
- There are plenty of samples in the HttpSecurity Javadoc. Be sure to check out the Javadoc on individual methods which gives examples for how to do things like openid, remember me, etc.
- Web 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.
Feedback Please
If you encounter a bug, have an idea for improvement, etc please do not hesitate to bring it up! We want to hear your thoughts so we can ensure we get it right before the code is generally available. Trying out new features early is a good and simple way to give back to the community. This also ensures that the features you want are present and working as you think they should
Please log any issues or feature requests to the Spring Security JIRA under the category “Java Config”. After logging a JIRA, we encourage (but do not require) you to submit your changes in a pull request. You can read more about how to do this in the Contributor Guidelines
If you have questions on how to do something, please use the Spring Security forums or Stack Overflow with the tag spring-security (I will be monitoring them closely). If you have specific comments questions about this blog, feel free to leave a comment. Using the appropriate tools will help make it easier for everyone.
Conclusion
You should have a fairly good idea of how to use Spring Security Java configuration for web based security. In the next post, we will take a look at how to setup method based security with Java configuration.
Spring Security Java Config Preview: Method Security
Update
Users should refer to the Spring Security Reference which contains more up to date information.
Original Blog Post
This is the third installment of a four part blog series. In my first post, I introduced Spring Security Java configuration and discussed some of the logistics of the project. In my previous post, we walked through a few examples of configuring web based security.
In this post, I will discuss how to configure method based security using Spring Security Java configuration. Like our previous post, we will start off with a very basic example and follow it up with an example that performs a bit of customization.
MethodSecurityService
While not terribly interesting, assume that we have a service called MethodSecurityService as shown below:
public interface MethodSecurityService {
@PreAuthorize("hasRole('ROLE_USER')")
String requiresUserRole();
}
Our implementation is just as trivial, but will ensure we focus on Spring Security rather than our services.
public class MethodSecurityServiceImpl implements
MethodSecurityService {
public String requiresUserRole() {
return "You have ROLE_USER";
}
}
Hello Method Security
By using @EnableGlobalMethodSecurity
we can easily secure our methods with Java configuration. Note that methodSecurityService
is not really part of our Security configuration, but we must create our MethodSecurityService
using Spring so that it can have Security applied to it.
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class HelloMethodSecurityConfig {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@Autowired
public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
This configuration is fairly similar to the following XML configuration:
<global-method-security pre-post-annotations="enabled"/>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="password" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="methodSecuriytService" class="MethodSecurityServiceImpl"/>
With our configuration, the invocation of requiresUserRole() on our methodSecurityService bean would require that the current user be authenticated with the role “ROLE_USER”. If the user was unauthenticated or did not have the role “ROLE_USER” a AccessDeniedException would be thrown.
Custom Method Security
There are a number of additional attributes available on the @EnableWebSecurity annotation, but if you wish to customize method security in more advanced ways you will need to extend GlobalMethodSecurityConfiguration. An example where we customize the PermissionEvaluator can be seen below:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@Override
protected MethodSecurityExpressionHandler expressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
@Autowired
public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
This is fairly similar to the following XML configuration:
<global-method-security pre-post-annotations="enabled">
<expression-handler ref="expressionHandler"/>
</global-method-security>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="password" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="methodSecuriytService" class="MethodSecurityServiceImpl"/>
<beans:bean id="expressionHandler" class="CustomExpressionHandler"/>
Additional Method Samples
We have given a few examples of how the Spring Security Java Configuration can be used to secure your application with method level security. You can find additional samples in the spring-security-javaconfig project’s github repository.
Feedback Please
If you encounter a bug, have an idea for improvement, etc please do not hesitate to bring it up! We want to hear your thoughts so we can ensure we get it right before the code is generally available. Trying out new features early is a good and simple way to give back to the community. This also ensures that the features you want are present and working as you think they should.
Please log any issues or feature requests to the Spring Security JIRA under the category “Java Config”. After logging a JIRA, we encourage (but do not require) you to submit your changes in a pull request. You can read more about how to do this in the Contributor Guidelines
If you have questions on how to do something, please use the Spring Security forums or Stack Overflow with the tag spring-security (I will be monitoring them closely). If you have specific comments questions about this blog, feel free to leave a comment. Using the appropriate tools will help make it easier for everyone.
Conclusion
You should now have an understanding of how to configure method based security using Spring Security Java configuration support. In the next post, we will demonstrate how Spring Security is designed for extension by walking through the OAuth Java Configuration proof of concept.
Spring Security Java Config Preview: OAuth
This is the fourth post in my five part blog series that introduces Spring Security Java configuration. In this post, we will discuss how Spring Security Java configuration can be extended by walking through Spring Security OAuth Java configuration support.
Proof of Concept
While the Spring Security Java configuration works well for very basic configuration, it is just a proof of concept. We have not ensured that all the functionality available in the XML namespace is present within its Java configuration support. It was important to ensure that Spring Security’s Java configuration would work well with the Spring extensions. However, we did not want to wait until we implemented all the configuration functionality in the extensions before releasing Spring Security Java config. In the future, we plan to solidify the Spring Security OAuth Java configuration but for now it is more of a proof of concept than a complete solution.
HelloOAuth2ServerConfiguration
Spring Security’s OAuth Java configuration supports a basic OAuth 2 server configuration. In its simplest form, it looks like this:
@Configuration
@EnableWebSecurity
public class HelloOAuth2ServerConfiguration
extends OAuth2ServerConfigurerAdapter {
private static final String RESOURCE_ID = "photos";
@Autowired
public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.apply(new InMemoryClientDetailsServiceConfigurer())
.withClient("my-client")
.resourceIds(RESOURCE_ID)
.authorizedGrantTypes("authorization_code","implicit")
.authorities("ROLE_USER")
.scopes("read","write")
.secret("secret");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.anyRequest().authenticated()
.and()
.apply(new OAuth2ServerConfigurer())
.resourceId(RESOURCE_ID);
}
}
With this configuration we are now able to processes OAuth request. However, it has some limitations that will not work in many circumstances:
- If user’s are approving requests with the OAuth Server, we would still need to a Controller that processes “/oauth/confirm_access”
- There is no way to authenticate with a user rather than an OAuth client which means there is no way for a user to confirm access
- Authorization is mapped to being authenticated, which is at best a naive implementation of authorization
SecurityConfigurer
Sitting these problems aside, let’s take a look at what is happening. The OAuth2ServerConfigurer is an instance of SecurityConfigurer. When implementing SecurityConfigurer, it is recommended to extend SecurityConfigurerAdapter which is a base implementation of SecurityConfigurer.
By allowing HttpSecurity to accept a SecurityConfigurer, we can add extensions (like OAuth) that update the HttpSecurity object in more complex ways. In fact, methods like HttpSecurity.formLogin() are implemented using SecurityConfigurerAdapter implementations as well. The difference is that they are part of Spring Security’s core modules and so there are convenience methods that perform the apply(SecurityConfigurerAdapter) for us.
Not only can we apply a SecurityConfigurer to the HttpSecurity object, we can also apply a SecurityConfigurer to the AuthenticationManagerBuilder. This is illustrated by the InMemoryClientDetailsServiceConfigurer. This means that the authentication mechanisms can be easily extended too.
What does this mean to you? Assume you have a more complicated Security configuration and want to share it across your company. You could allow engineers to copy paste the configuration everywhere. Alternatively, you can create your own SecurityConfigurerAdapter implementation that allows developers to focus on your company’s custom DSL.
Additional OAuth Samples
Our sample configuration we provided was very simple, but it does not illustrate what to do in more realistic situations. We will not blog about these until we feel the OAuth support has been solidified further. However, there are additional samples that can get you started if you wish to try it out.
- Spring Security JavaConfig's sparklr application
- The Spring Rest Stack's - oauth module
Feedback Please
If you encounter a bug, have an idea for improvement, etc please do not hesitate to bring it up! We want to hear your thoughts so we can ensure we get it right before the code is generally available. Trying out new features early is a good and simple way to give back to the community. This also ensures that the features you want are present and working as you think they should.
Please log any issues or feature requests to the Spring Security JIRA under the category “Java Config”. After logging a JIRA, we encourage (but do not require) you to submit your changes in a pull request. You can read more about how to do this in the Contributor Guidelines
If you have questions on how to do something, please use the Spring Security forums or Stack Overflow with the tag spring-security (I will be monitoring them closely). If you have specific comments questions about this blog, feel free to leave a comment. Using the appropriate tools will help make it easier for everyone.
Conclusion
Spring Security Java configuration used the OAuth support as a proof of concept to ensure it is ready for extension. In time, the OAuth support will be solidified into a replacement for the XML configuration. In my last post I discuss the readability of Spring Security Java Configuration.
Spring Security Java Config Preview: Readability
In this post, I will discuss how to make your Spring Security Java configuration more readable. The post is intended to elaborate on a point from Spring Security Java Config Preview: Web Security where I stated:
By formatting our Java configuration code it is much easier to read. It can be read similar to the XML namespace equivalent where “and()” represents optionally closing an XML element.
Indentation
The indentation of Spring Security’s Java configuration really impacts its readability. In general, indentation like a bullet list should be preferred.
For a more concrete example, take a look at the following code:
http
// #1
.formLogin()
// #2
.loginPage("/login")
.failureUrl("/login?error")
// #3
.and()
// #4
.authorizeRequests()
// #5
.antMatchers("/signup","/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
- #1
formLogin
updates thehttp
object itself. The indentation offormLogin
is incremented from that ofhttp
(much like they way the<form-login>
is indented from<http>
) - #2
loginPage
andfailureUrl
update theformLogin
configuration. For example,loginPage
determines where Spring Security will redirect if log in is required. For this reason, each is a child offormLogin
. - #3
and
means we are done configuring the parent (in this caseformLogin
). This also implies that the next line will decrease indentation by one. When looking at the configuration you can read it ashttp
is configured withformLogin
andauthorizeRequests
. If we had nothing else to configure, theand
is not necessary. - #4 We decrease the indentation with
authorizeRequests
since it is not related to form based log in. Instead, its intent is to restrict access to various URLs. - #5 each
antMatchers
andanyRequest
modifies the authorization requirements forauthorizeRequests
. This is why each is a child ofauthorizeRequests
IDE Formatters
The indentation may cause problems with code formatters. Many IDE’s will allow you to disable formatting for select blocks of code with comments. For example, in STS/Eclipse you can use the comments of @formatter:off and @formatter:on to turn off and on code formatting. An example is shown below:
// @formatter:off
http
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.and()
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
// @formatter:on
For this feature to work, make sure you have it enabled:
- Navigate to Preferences -> Java -> Code Style -> Formatter
- Click the Edit button
- Select the Off/On Tags tab
- Ensure Enable Off/On tags is selected
- You can optionally change the strings used for disabling and enabling formatting here too.
- Click OK
Comparison to XML Namespace
Our indentation also helps us relate the Java Configuration to the XML namespace configuration. This is not always true, but it does help. Let’s compare our configuration to the relevant XML configuration below.
http
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.and()
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
The relevant, but not equivalent, XML configuration can be seen below. Note that the differences between how Spring Security will behave between these configurations is due to the different default values between Java Configuration and XML configuration.
<http use-expressions="true">
<form-login
login-page="/login"
authentication-failure-url="/login?error"
/> <!-- similar to and() -->
<intercept-url pattern="/signup" access="permitAll"/>
<intercept-url pattern="/about" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
</http>
- The first thing to notice is that the
http
and<http>
are quite similar. One difference is that Java Configuration usesauthorizeRequests
to specifyuse-expressions="true"
formLogin
and<form-login>
are quite similar. Each child offormLogin
is an XML attribute of<form-login>
. Based upon our explanation of indentation, the similarities are logical since XML attributes modify XML elements.- The
and()
underformLogin
is very similar to ending an XML element. - Each child of
authorizeRequests
is similar to each<intercept-urls>
, except that Java Configuration specifies requires-channel differently which helps reduce configuration in many circumstances.
Summary
You should now know how to consistently indent your Spring Security Java Configuration. By doing so your code will be more readable and be easier to translate to and from the XML configuration equivalents.
微信公众号: 架构师日常笔记 欢迎关注!