Spring Security是一款基于Spring的安全框架,主要包含认证和受权两大安全模块,和另一款流行的安全框架Apache Shiro相比,它拥有更为强大的功能。Spring Security也能够轻松的自定义扩展以知足各类需求,而且对常见的Web安全攻击提供了防御支持。若是你的Web框架选择的是Spring,那么在安全方面Spring Security会是一个不错的选择。web
这里咱们使用Spring Boot来集成Spring Security,Spring Boot版本为1.5.14.RELEASE,Spring Security版本为4.2.7RELEASE。spring
建立一个Spring Boot项目,而后引入spring-boot-starter-security:浏览器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
接下来咱们建立一个TestController,对外提供一个/hello服务:安全
@RestController
public class TestController {
@GetMapping("hello")
public String hello() {
return "hello spring security";
}
}
这时候咱们直接启动项目,访问http://localhost:8080/hello,可看到页面弹出了个HTTP Basic认证框:app
当Spring项目中引入了Spring Security依赖的时候,项目会默认开启以下配置:框架
security:
basic:
enabled: true
这个配置开启了一个HTTP basic类型的认证,全部服务的访问都必须先过这个认证,默认的用户名为user,密码由Sping Security自动生成,回到IDE的控制台,能够找到密码信息:ide
Using default security password: e9ed391c-93de-4611-ac87-d871d9e749ac
输入用户名user,密码e9ed391c-93de-4611-ac87-d871d9e749ac后,咱们即可以成功访问/hello接口。spring-boot
咱们能够经过一些配置将HTTP Basic认证修改成基于表单的认证方式。spa
建立一个配置类BrowserSecurityConfig继承org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter这个抽象类并重写configure(HttpSecurity http)方法。WebSecurityConfigurerAdapter是由Spring Security提供的Web应用安全配置的适配器:debug
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单方式
.and()
.authorizeRequests() // 受权配置
.anyRequest() // 全部请求
.authenticated(); // 都须要认证
}
}
Spring Security提供了这种链式的方法调用。上面配置指定了认证方式为表单登陆,而且全部请求都须要进行认证。这时候咱们重启项目,再次访问http://localhost:8080/hello,能够看到认证方式已是form表单的方式了:
用户名依旧是user,密码由Spring Security自动生成。当输入凭证错误时,页面上将显示错误信息:
若是须要换回HTTP Basic的认证方式,咱们只须要简单修改configure方法中的配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.formLogin() // 表单方式
http.httpBasic() // HTTP Basic方式
.and()
.authorizeRequests() // 受权配置
.anyRequest() // 全部请求
.authenticated(); // 都须要认证
}
上面咱们开启了一个最简单的Spring Security安全配置,下面咱们来了解下Spring Security的基本原理。经过上面的的配置,代码的执行过程能够简化为下图表示:
如上图所示,Spring Security包含了众多的过滤器,这些过滤器造成了一条链,全部请求都必须经过这些过滤器后才能成功访问到资源。其中UsernamePasswordAuthenticationFilter过滤器用于处理基于表单方式的登陆认证,而BasicAuthenticationFilter用于处理基于HTTP Basic方式的登陆验证,后面还可能包含一系列别的过滤器(能够经过相应配置开启)。在过滤器链的末尾是一个名为FilterSecurityInterceptor的拦截器,用于判断当前请求身份认证是否成功,是否有相应的权限,当身份认证失败或者权限不足的时候便会抛出相应的异常。ExceptionTranslateFilter捕获并处理,因此咱们在ExceptionTranslateFilter过滤器用于处理了FilterSecurityInterceptor抛出的异常并进行处理,好比须要身份认证时将请求重定向到相应的认证页面,当认证失败或者权限不足时返回相应的提示信息。
下面咱们经过debug来验证这个过程(登陆方式改回表单的方式)。
咱们在/hello服务上打个断点:
在FilterSecurityInterceptor的invoke方法的super.beforeInvocation上打个断点:
当这行代码执行经过后,即可以调用下一行的doFilter方法来真正调用/hello服务,不然将抛出相应的异常。
当FilterSecurityInterceptor抛出异常时,异常将由ExceptionTranslateFilter捕获并处理,因此咱们在ExceptionTranslateFilter的doFilter方法catch代码块第一行打个断点:
咱们待会模拟的是用户未登陆直接访问/hello,因此应该是抛出用户未认证的异常,因此接下来应该跳转到UsernamePasswordAuthenticationFilter处理表单方式的用户认证。在UsernamePasswordAuthenticationFilter的attemptAuthentication方法上打个断点:
准备完毕后,咱们启动项目,而后访问http://localhost:8080/hello,代码直接跳转到FilterSecurityInteceptor的断点上:
往下执行,由于当前请求没有通过身份认证,因此将抛出异常并被ExceptionTranslateFilter捕获:
捕获异常后重定向到登陆表单登陆页面,当咱们在表单登陆页面输入信息点login后,代码跳转到UsernamePasswordAuthenticationFilter过滤器的attemptAuthentication方法上:
判断用户名和密码是否正确以后,代码又跳回FilterSecurityInterceptor的beforeInvocation方法执行上:
当认证经过时,FilterSecurityInterceptor代码往下执行doFilter,而后代码最终跳转到/hello上:
浏览器页面将显示hello spring security信息。