- 前言
- OAuth2 生态
- 关于 OAuth2
- Spring Security
- FilterChainProxy
- SecurityFilterChain 定义示例
- 总结
之前或多或少的接触过 Spring Security
,最近有契机基于 Spring Security
搭建了一套较完整的 OAuth2
认证服务,对 Spring Security
对 OAuth2
支持的生态做了简单的了解,以此文分享
- 现在的
Spring Security
是独立完整的项目,囊括了对oauth2
等的支持而不是基于之前的Spring Security OAuth2
项目独立实现(原项目已@Deprecated
) Spring Security oauth2
模块支持oauth2-client
oauth2-resource-server
oauth2-jose
,不再提供认证中心
的支持- 认证中心由单独的新项目
spring-security-oauth2-authorization-server
支持 ,该项目是由Spring Security
团队牵头的社区开源项目,目前正式版本仅为0.2.3
spring-security-oauth2-authorization-server
目前并没有或者说并没有特别成熟的Spring Boot
自动装配支持,但实际上作为较新的项目,其配置方式已经很大程度上向Spring Boot
靠拢(而不是传统的@EnabledXXX
模式)- 以上是当前
Spring Security
(准确的说是Spring
)对OAuth2
支持的最 新 生态,本着技术就要用新的
的原则,个人项目完全基于该生态搭建
- 这里不会去聊
OAuth2
的细节,只想聊下OAuth2
对我思考方式和对 【规范】二字理解的影响 - 说来说去,无论新的生态还是老的技术,无非是实现和使用上的区别,其底层的规范、理解还是基于
OAuth2
本身定义的,因此对这些生态组件的学习、理解很大程度就基于对规范的理解 - 规范往往看似通俗易懂却又字字细节,就像我自认为了解
OAuth2
规范,但又说不出个一二三来,这让我意识到规范是很值得咬文嚼字
的东西 - 比如
OAuth2
最常规的模式:授权码模式
中,用户是基于代理(浏览器)被Client
重定向 到认证中心
与认证中心
单独交互 从而保证授权码过程对Client
无感,而不应该笼统的描述为Client
从认证中心
获取授权码
,两者相差甚远 - 这对学习、使用实现组件比如
Spring Security
时的影响是很大的,或者对是否、为什么选择OAuth2
的何种模式都是很关键的 - 综上所述,如果想提高
OAuth2
生态组件的使用体验,首先深度的回顾一下OAuth2
规范是很有必要的 - 贴一张
授权码模式
的序列图,思考一下
Spring
体系下OAuth2
的实现,前面提到,它提供Client
ResourceServer
的支持,AuthorizationServer
的部分由另一个项目支持- 笼统地说,它基于一组一组的
Filter
实现,对应路由的一组Filter
封装成一个SecurityFilterChain
,由我们以Bean
组件的形式提供,最终以一个FilterChainProxy
实例的形式注册到Web
容器(Servlet
)中
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
// 获取请求对应的 Filter 组
List<Filter> filters = getFilters(firewallRequest);
// 如果没有就继续执行
if (filters == null || filters.size() == 0) {
firewallRequest.reset();
chain.doFilter(firewallRequest, firewallResponse);
return;
}
// 如果存在就执行这些 Filter
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
virtualFilterChain.doFilter(firewallRequest, firewallResponse);
}
------------------ getFilters ------------
private List<Filter> getFilters(HttpServletRequest request) {
int count = 0;
// filterChains:即用户注册的所有 SecurityFilterChain
for (SecurityFilterChain chain : this.filterChains) {
// 根据路由匹配,返回匹到的第一个
if (chain.matches(request)) {
return chain.getFilters();
}
}
return null;
}
FilterChainProxy
的部分源码:
- 拦截请求并获取对应的 (
Spring Security
)Filter
组,如果有就执行过滤逻辑 - 这些
Filter
就是普通的Servlet Filter
,通常有Spring Security
内置或用户自定义,但它们不是直接注册到Servlet
容器里,而是注册到SecurityFilterChain
里 getFilters
的逻辑就是遍历所有SecurityFilterChain
,返回第一个匹配SecurityFilterChain
的Filter
组,因此SecurityFilterChain
的匹配器(RequestMather
)和顺序定义很重要
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSFC(HttpSecurity httpSecurity) throws Exception {
// 匹配一组 AuthorizationServer 相关的路由
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(httpSecurity);
return httpSecurity
.formLogin()
.and()
.build();
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
public SecurityFilterChain loginSFC(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.requestMatcher(new AntPathRequestMatcher(
"/login"
))
.authorizeHttpRequests()
// 放开 login
.anyRequest().permitAll()
.and()
// 关闭跨域
.csrf().disable()
.build();
}
@Bean
public SecurityFilterChain defaultWebSFC(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().disable()
.build();
}
- 如上是
AuthorizationServer
的一段SecurityFilterChain
配置示例 @Order
注解指定对应的优先级,依次定义了三级过滤:
-AuthorizationServer
通过的对内置路由的处理,比如/oauth2/authorize
/oauth2/token
等路由忽略跨域等
- 自定义了一个指定了RequestMatcher
的SecurityFilterChain
,处理/login
端口
- 兜底SecurityFilterChain
未指定RequestMatcher
,则匹配所有剩余的路由并处理它们:示例中的配置标识上述端口需要认证才能访问
- 断点下的优先级如下,则拦截到的请求返回第一个匹配到SecurityFilterChain
的Filter
组
- 本文从
Spring Security
对OAuth2
的支持入手,简单的了解了下当前最 新 的生态环境 OAuth2
规范的理解,对Spring Security
的使用很有帮助- 浅入浅出的聊了下
Spring Security
的架构,因此对OAuth2
各组件的支持就是提供对应的Filter
SecurityFilterChain
式的安全策略配置应该是Spring Security
与Spring Security OAuth2
最大的不同(我猜的,后者我并没有完整的使用过)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)