Spring Security Java Config Preview: Web Security
Spring Security是一个强大而灵活的安全框架,它提供了多种方式来保护Java应用程序。在Spring Security中,Web安全性是通过配置来实现的,这些配置可以是XML格式、Java注解或者纯Java配置。下面我将介绍如何使用Java配置来设置Web安全性。
首先,你需要在你的项目中添加Spring Security的依赖。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.4.2</version>
</dependency>
接下来,你需要创建一个配置类来定义你的Web安全性。这个类应该继承自WebSecurityConfigurerAdapter
,并重写其中的configure(HttpSecurity http)
方法来设置具体的安全规则。例如:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 要求所有请求都需要认证
.authorizeRequests()
.anyRequest().authenticated()
.and()
// 定义登录页面和默认的成功处理方式
.formLogin()
.loginPage("/login")
.permitAll()
.and()
// 登出功能
.logout()
.permitAll();
}
}
在上面的例子中,我们设置了所有的请求都需要进行认证,指定了登录页面为"/login",并且允许所有人访问登录页面和登出功能。
此外,你还可以通过重写configure(AuthenticationManagerBuilder auth)
方法来配置用户认证的细节,比如使用内存中的用户存储:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER");
}
这样,我们就完成了一个基本的Web安全性配置。你可以根据需要进一步定制和扩展这个配置,以满足你的应用的安全需求。
在Spring Security中,角色基权限控制(Role-Based Access Control, RBAC)是通过对用户分配不同的角色,并基于这些角色来控制对资源的访问。以下是实现角色基权限控制的步骤:
-
配置用户和角色:首先需要定义用户及其角色。这通常通过一个自定义的用户服务来实现,该服务从数据库或其他存储机制中加载用户信息和角色。
-
配置安全上下文:使用
UserDetailsService
接口来获取用户详细信息,包括用户名、密码以及角色列表。这个接口的实现类会负责从数据源中检索用户信息。 -
配置认证管理器:创建一个
AuthenticationManager
实例,它将用于处理身份验证请求。 -
配置授权管理器:创建一个
AccessDecisionManager
实例,它负责决定是否允许特定用户执行某个操作。这个决策基于用户的权限和请求的资源。 -
配置过滤器链:定义一系列的过滤器,如
UsernamePasswordAuthenticationFilter
用于处理登录请求,ExceptionTranslationFilter
用于处理异常情况等。这些过滤器按照一定的顺序排列,形成过滤链。 -
配置URL访问规则:使用
HttpSecurity
对象配置哪些URL需要保护,以及不同角色可以访问哪些资源。例如,可以通过authorizeRequests()
方法指定只有具有特定角色的用户才能访问某些端点。 -
启动安全性:最后,确保启用了Spring Security的安全功能,通常是通过调用
configure(HttpSecurity http)
方法来完成。
通过上述步骤,可以在Spring Security中实现基于角色的访问控制,从而根据用户的角色限制对系统资源的访问。
Engineering
Rob Winch
July 03, 2013
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
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:
org.springframework.web.context.ContextLoaderListener contextConfigLocation /WEB-INF/spring/*.xml“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.
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 and REQUEST
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:
springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /* ERROR REQUESTCustomWebSecurityConfigurerAdapter
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:
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.
comments powered by Disqus
translate:
翻译:
用户应该参考包含更多最新信息的Spring安全性参考。
原创博客文章
在上一篇文章中,我介绍了Spring Security Java配置,并讨论了项目的一些逻辑。在本文中,我们将首先介绍一个非常简单的web安全配置。然后,我们将为定制的配置增添一些趣味。
你好网络安全