Spring Security介绍
Spring Security
是为Spring应用程序提供声明式安全保护
的安全性框架。
能够在web请求级别
和方法调用级别
处理身份认证和授权。
它使用Filter
保护web请求并限制URL级别的访问。使用Spring Aop
保护方法调用,确保只有具备适当权限的用户才能访问安全保护的方法。
想使用Spring Security
哪些功能,首先要做的就是将对应的SpringSecurity模块
添加到应用程序的类路径下。
Spring Security
分为11个模板。不一一介绍。
我们至少要包含Core
(提供Spring Security基本库)和Configuration
(包含通过XML和Java配置Spring Security的功能支持)这两个模块。对于web应用还需要添加web模块
。
web安全性配置
Spring Security
依赖一系列Servlet Filter
来提供不同的安全特性,当我们启用web安全性@EnableWebSecurity
时,会自动创建这些Filter。
最简单的安全性配置
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
@EnableWebSecurit
y注解将会启用Web安全功能。但它本身并没有什么用
处,Spring Security
必须配置在一个实现了WebSecurityConfigurer
的bean中,或者(简单起见)扩展WebSecurityConfigurerAdapter
。
如此配置以后,这个应用就被锁定了,任何url访问都会跳到默认的登录页面。
用户名默认user,密码在启动应用时会在控制台输出。
这并不是我们想要的,我们需要指定web安全的细节,通过重载WebSecurityConfigurerAdapter
中一个多个方法来实现。
通过一个例子来了解,我们希望提供如下细节:
- 配置用户存储;
- 指定哪些请求需要认证,哪些请求不需要认证,以及所需要的权限;
- 提供一个自定义的登录页面,替代原来简单的默认登录页。
用户存储:就是用户名、密码以及其他信息存储的地方,在进行认证决策的时候,会对其进行检索。Spring Security
能够基于各种数据存储来认证用户,如内存、关系型数据库以及LDAP,也可以自定义的用户存储实现。
内存用户存储最简单,下面是内存存储的配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() //启用用户存储
.withUser("user").password("123456").roles("USER") //添加一个角色为USER的用户
.and() //连接多个配置
.withUser("admin").password("123456").roles("ADMIN","USER");//再添加一个角色为ADMIN,USER的用户
}
}
重载configure()
方法,并以AuthenticationManagerBuilder
作为传入参数。AuthenticationManagerBuilder
的inMemoryAuthentication()
方法启用、配置并任意填充基于内存的用户存储。withUser(username)
添加用户名为username的用户,返回UserDetailsBuilder
对象来进一步配置此用户的信息。
下面是配置如何通过拦截器保护请求
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/**").hasRole("USER") ///users路径下的页面需要USER用户权限
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().permitAll()
.and().formLogin() //启用基本登录页默认“/login”
.and().rememberMe() //启用rememberMe功能
;
}
自定义登录页面/login之前,我们先观察spring security
内置的默认页面代码:
<h3>Login with Username and Password</h3>
<form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
//csrf跨站请求防御,添加的_csrf域
<input name="_csrf" type="hidden" value="a502dd37-4088-454f-96d0-ce4073340789" />
</table>
spring security
默认开启csrf跨站请求防御,一旦开启每个post请求在表单都必须添加_csrf域,详情见csrf。
自定义登录页面需要注意的一个关键点是<form>
提交到了什么地方。同时还需要注意username
和password
输入域,在你的登录页中,需要同样的输入域。最后,假设没有禁用CSRF的话,还需要保证包含了值为CSRF token
的“_csrf”输入域。