Spring Security
Spring Security
Spring Security
是一个功能强大且高度可定制的身份验证和访问控制框架。
它是保护基于Spring
的应用程序的官方标准。毕竟是全家桶套餐中的一员。Spring Security
是一个专注于为Java
应用程序提供身份验证和授权的框架。 像所有Spring
项目一样,Spring Security
的真正强大之处在于它可以轻松扩展以满足自定义需求。
核心功能
- 认证(你是谁)
- 授权(你能干啥)
- 攻击防护(防止伪造身份)
基本原理
上面是Spring Security
的基本原理图,最右边就是我们的Controller
接口,前面的所有都是过滤器。
简单理解:Spring Security
就是一组过滤器,它的核心也就是这样的一条过滤链,访问的所有请求都会经过 Spring Security 的过滤器。
过滤器链上有很多的过滤器,它们的作用就是用来校验用户的身份,每一个过滤器负责处理一种认证方式。
比如:http.formLogin()
对应着UsernamePasswordAuthenticationFilter
过滤器。
比如:http.httpBasic()
对应着BasicAuthenticationFilter
过滤器。
请求到达过滤器时,如UsernamePasswordAuthenticationFilter
这个过滤器时,就会触发当前请求是否是一个登陆请求,判断请求中是否携带用户名和密码等。如果符合条件,那么过滤器就会试图去登陆,若是不满足条件,就会下发给下一个过滤器。
例如UsernamePasswordAuthenticationFilter
下一个过滤器是BasicAuthenticationFilter
。到达BasicAuthenticationFilter
后又会判断是否触发当前过滤器的条件,如请求头中是否携带Basic
登陆的信息,如果有就会尝试解码和登陆。
其他自定义过滤器也是同样的逻辑,按照这个流程一个个的往下走。
如果在某个过滤器上认证成功后会在请求上做一个标记,用来表示当前这个请求的用户授权成功了。
ExceptionTranslationFilter
ExceptionTranslationFilter
异常转换过滤器位于整个过滤链的后方,用来转换整个链路中出现的异常,将其转化,顾名思义,转化以意味本身并不处理。
一般其只处理两大类异常:
AccessDeniedException
访问异常;AuthenticationException
认证异常;
这个过滤器非常重要,因为它将Java
中的异常和HTTP
的响应连接在了一起,这样在处理异常时,我们不用考虑密码错误该跳到什么页面,账号锁定该如何,只需要关注自己的业务逻辑,抛出相应的异常便可。
如果该过滤器检测到AuthenticationException
,则将会交给内部的AuthenticationEntryPoint
去处理,如果检测到AccessDeniedException
,需要先判断当前用户是不是匿名用户,如果是匿名访问,则和前面一样运行AuthenticationEntryPoint
,否则会委托给AccessDeniedHandler
去处理,而AccessDeniedHandler
的默认实现,是AccessDeniedHandlerImpl
。
所以ExceptionTranslationFilter
内部的AuthenticationEntryPoint
是至关重要的,顾名思义:认证的入口点。
FilterSecurityInterceptor
走过前面所有的过滤器后最后会来到FilterSecurityInterceptor
,这个过滤器是整个 Spring Security 过滤器链上的最后一环,它能够决定请求能不能访问 API 请求。
FilterSecurityInterceptor
从SecurityContextHolder
中获取Authentication
对象,然后比对用户拥有的权限和资源所需的权限。前者可以通过Authentication
对象直接获得,而后者则需要引入我们之前一直未提到过的两个类:SecurityMetadataSource
、AccessDecisionManager
。
已注销-FilterSecurityInterceptor详解
银河架构师-FilterSecurityInterceptor详解
表单认证
源码分析
AuthenticationManager
自己并不包含验证的逻辑,它的作用是用来管理AuthenticationProvider
。
getProviders()
会拿到整个系统中所有实现AuthenticationProvider
的实现类,这里上面提到的AuthenticationManager
就是来收集并管理所有AuthenticationProvider
的实现类,这里就会循环挨个去比对上面AuthenticationToken
类型。
不同的Provider
支持的Authentication
类型是不一样的,根据传入的Authentication
类型这里会挑出一个进行校验处理。
认证的结果如何在请求间共享
授权流程
Spring Security
真正判断请求能否通过是在FilterSecurityInterceptor
过滤器中处理的,如果请求不能通过的话就会根据不同的原因抛出异常,抛出异常以后就会由ExceptionTranslationFilter
这个过滤器接收处理。
但有一个特殊的过滤器AnonymousAuthenticationFilter
AnonymousAuthenticationFilter
AnonymousAuthenticationFilter
中的逻辑比较简单,就是判断当前的SecurityContextHolder
中是否有authentication
,是否等于null
。
这里的判断实际上就在在判断前面的过滤器是否完成身份的认证,或者在Session
中拿到身份的证信息。
如果前面的过滤器一个都没认证的话,那么就会创建一个authentication
然后set
到SecurityContextHolder
中,这里放的并不是认证成功后的用户信息,而是一个字符串anonymousUser
。
在Spring Security
中,AnonymousAuthenticationFilter
是所有认证过滤器的最后一个,也就是不管你前面有没有身份认证成功,SecurityContextHolder
中一定是会放一个authentication
的。如果前面的过滤器认证成功了,那么放的就是用户身份信息,如果一个都没成功,那么就是一个字符串anonymousUser
。
核心:FilterSecurityInterceptor
、AccessDecisionManager
、AccessDecisionVoter
。
FilterSecurityInterceptor
:它是授权的主入口。
AccessDecisionManager
:访问决定的管理者,是一个接口,它有一个抽象实现AbstractAccessDecisionManager
和三个具体实现AffirmativeBased
、ConsensusBased
、UnanimousBase
。它也管理者一组AccessDecisionVoter
。
AccessDecisionVoter
:从名字就能看出它是做投票的。
当AccessDecisionManager
收到一个请求时这一组AccessDecisionVoter
会根据自己的逻辑判断这个请求时过还是不过。
判断有三套逻辑:
AffirmativeBased
:不管有多少个AccessDecisionVoter
投不过,只要有一个投通过,那么请求就可以访问。(Spring Security的默认实现逻辑)UnanimousBased
:不管有多少个AccessDecisionVoter
投通过,只要有一个投不通过,那么请求就不可以访问。ConsensusBased
:判断通过的AccessDecisionVoter
多还是不通过的多,哪个多就是哪个。
在判断一个请求能不能过需要两块数据:ConfigAttribute
、Authentication
。
ConfigAttribute
请求的权限信息ConfigAttribute
。例:a请求需要什么权限,b请求需要什么权限。
请求到达FilterSecurityInterceptor
时就会把这个请求路径所需的权限读出来,封装成一组ConfigAttribute
对象。
Authentication
Authentication
实际上就是当前请求的用户的权限信息,也就是当前用户有哪些权限,这个信息就是封装在Authentication
里。
- 0
- 0
-
分享