前言
记录对Spring Security过滤流程的梳理结果
总览
当用户端发送请求到我们的Web应用时,首先是Container(例如Tomcat)接收到请求,然后通过一系列的Filter后到达具体的Servlet
Filter顺序在Spring Boot中有两种控制机制
-
Filter类型的Bean使用@Order注解或实现Ordered接口 - 使用
FilterRegistrationBean为其设置顺序
Spring Security在其中的角色就是众多Filter 中的一个,其具体类型为 FilterChainProxy ,顾名思义,它内部处理流程其实也是 FilterChain
实际上,被直接安装到Container中的Filter其实是DelegatingFilterProxy,它本身不实现任何逻辑,仅仅是FilterChainProxy的代理
FilterChainProxy内部拥有多条SecurityFilterChain,它会根据Url选择最匹配的FilterChain进行处理
SecurityFilterChain
安全一般包含两个问题:
-
Authentication:你是谁 -
Authorization:你能做什么
所以每条SecurityFilterChain都要解决这两个问题
Authentication
AuthenticationManager是Spring Security中身份认证策略的主要接口
它只有一个方法authenticate:
- 认证通过则返回
Authentication对象 - 认证失败则抛出
AuthenticationException - 无法判断则返回
null
而ProviderManager则是最常用的实现类,它内部其实是一条AuthenticationProvider组成的处理链
AuthenticationProvider与AuthenticationManager类似,但它多一个方法:
authenticate-
supports(供调用者判断其是否能处理相关类型认证)
通常对于系统内的不同资源我们会有不同的认证策略(不同的SecurityFilterChain),每一种策略都有各自的AuthenticationManager进行管理。我们在配置AuthenticationManager时一般只是配置从哪里获取用户信息,其内部的处理链会使用这些信息进行认证
ProviderManger进行认证时会遍历处理链,找到能处理该类型认证的AuthenticationProvider并让其处理,如果没有找到相应的AuthenticationProvider或其处理结果为null,则向可能存在的parent(Global ProviderManager)发出处理请求
Authorization
AccessDecisionManager是权限认证策略的主要接口,包含三个方法:
-
decide: 判断是否授权,void 方法,拒绝时抛出AccessDeniedException -
supports: 有两个重载方法,判断是否支持该类型权限的裁决
授权对通过认证后的Authentication进行裁决, AffirmativeBased是最常用的实现类,内部是由AccessDecisionVoter组成的处理链,与ProviderManager类似,不过它没有Parent
AffirmativeBased进行认证时直接遍历内部处理链直到某个AccessDecisionVoter返回确认或拒绝授权则处理结束。所有AccessDecisionVoter都弃权时则根据allowIfAllAbstainDecisions属性决定
Filter
SecurityFilterChain内部是javax.servlet.Filter组成的处理链,常见的如:
-
BasicAuthenticationFilter: 用户名密码验证 -
BearerTokenAuthenticationFilter: 基于token验证
Filter就是实现各种逻辑的主要地方,我们根据业务写的Filter也主要放在这里,Security自带的过滤器多会与AuthenticationManager互动
FilterSecurityInterceptor
每条SecurityFilterChain(默认或自定义)最后一个Filter必定是FilterSecurityInterceptor
在Spring Security中它决定Request最终能否通过过滤,主要行为是将通过前面所有Filter后AuthenticationManager产生的Authentication交由AccessDecisionManager处理,通过授权则通过过滤