当前位置:网站首页>【OAuth2】八、OAuth2登录的配置逻辑-OAuth2LoginConfigurer和OAuth2ClientConfigurer
【OAuth2】八、OAuth2登录的配置逻辑-OAuth2LoginConfigurer和OAuth2ClientConfigurer
2022-07-26 13:20:00 【北城小林】
OAuth2登录的配置逻辑
前言
Spring Boot中和OAuth2的默认配置梳理过了,里面有很多新概念。对于初学者可能不太好接受,今天我们深入Spring Security OAuth2登录的配置细节。
以下是HttpSecurity配置OAuth2登录的入口方法:
从上面的代码中很容易看得出OAuth2登录的细节都在OAuth2LoginConfigurer这个配置类中,只要搞明白它就能掌握配置细节了。
一 、OAuth2LoginConfigurer
OAuth2LoginConfigurer和FormLoginConfigurer是一个父类。OAuth2LoginConfigurer的这种配置方式,启用该配置类将为用户提供基于OAuth2或OpenID Connect 1.0协议的第三方登录能力。


1、共享对象的设置和使用
SharedObject(共享对象)是HttpSecurityBuilder提供的一个共享功能,目的就是让一个对象实例在多个配置类之间共享。举个例子,DefaultLoginPageGeneratingFilter很多自定义认证过滤器都要用到这个来生成默认页面,如果想共享就可以通过setSharedObject方法在SecurityConfigurer的init生命周期方法或者configure生命周期方法把DefaultLoginPageGeneratingFilter放进去。
AbstractHttpConfigurer和OAuth2LoginConfigurer都继承了AbstractHttpConfigurer
然后在其它SecurityConfigurer中就可以取出该共享对象来进行一些操作。
这一类对象被成为SharedObjects。OAuth2LoginConfigurer的几个共享对象都具有定制化的能力,稍后会用到它们。
2、四个端点配置
授权端点、token端点、重定向端点、用户信息端点都是OAuth2协议中的重要端点定义。这里也针对它们作出了一些配置,分别封装为上图③中对应的配置类供开发者配置
2.1 AuthorizationEndpointConfig
这个类负责授权端点的配置,有三个配置项。
authorizationRequestBaseUri
授权请求URI,默认值是/oauth2/authorization,通过baseUri方法可以自定义。比如前面DEMO中请求gitee授权就是/oauth2/authorization/gitee。OAuth2AuthorizationRequestResolver
该接口的详细分析参见本教程中OAuth2AuthorizationRequestRedirectFilter 详解AuthorizationRequestRepository

2.2 TokenEndpointConfig

这个类负责授权服务器Token端点的配置,仅仅有一个配置项,一个获取Token的抽象客户端接口:
默认配置为DefaultAuthorizationCodeTokenResponseClient。这个自定义的几率还挺高的,有些授权服务器可能有一些额外的参数。
上边接口中参数根据AuthorizationGrantType的类型目前有如下几个实现:
注意和OAuth2AuthorizationRequest的区别,比较相似!
2.3 RedirectionEndpointConfig
这个用来配置OAuth2LoginAuthenticationFilter的拦截URL,对应配置文件中的redirect-uri,默认是/login/oauth2/code/*。
2.4 UserInfoEndpointConfig

三个方法、获取用户信息、获取oidc用户信息、一个过时的配置
可以继承OAuth2UserRequest来自定义获取用户信息的请求参数,来获取OAuth2授权的用户信息OAuth2User,这里默认提供了OIDC的实现。
二、 OAuth2LoginConfigurer的初始化和配置
OAuth2LoginConfigurer是SecurityConfigurer的实现,它有两个方法,都非常重要:
- 一个是init方法,这个方法你可以认为是SecurityBuilder构造函数的逻辑。如果你想在SecurityBuilder初始化的时候执行一些逻辑或者在后续配置中共享一些变量的话就可以在init方法中去实现。
- 另一个方法是configure,为SecurityBuilder配置一些必要的属性。
这两个方法有着明确的先后执行顺序。在一次构建内可能有多个SecurityConfigurer,只有全部的init逐个执行完毕后才会逐个执行configure方法。之所以分这两个阶段,目的是更细粒度的控制配置项,例如在Configurer之间共享一些初始化项。
1、init方法


1.1 初始化OAuth2LoginAuthenticationFilter
OAuth2LoginAuthenticationFilter构造有三个参数,参数来源优先级如下图:
初始化完毕后通过setAuthenticationFilter方法设置,并没有加入过滤器链中。也就是说该过滤器还没有正式生效,还需要进一步的配置。
优先从SharedObjects(共享对象)中取,其实就是
JavaConfig中配置。
1.2 配置登陆认证入口逻辑
如果有个性化登录页,优先使用个性化登录页,如果没有还要再细分两种情况:
假如你只有一个第三方授权,肯定就不用选了,直接跳转到第三方应用的授权页。
假如你有两个第三方授权Gitee和Github,这里会给你构造一个中转页以方便你选择使用哪个授权。
1.3 初始化并设置OAuth2LoginAuthenticationProvider
这里OAuth2LoginAuthenticationProvider有三个配置项,初始化逻辑是这样的:
初始化后会保存为配置类OAuth2LoginConfigurer一个属性,和其它类型的AuthenticationProvider类似,OAuth2LoginAuthenticationProvider承担着OAuth2登录认证的具体逻辑,参见本教程关于OAuth2LoginAuthenticationFilter一文中对它的讲解。
OAuth2LoginAuthenticationProvider会通过http.authenticationProvider方法加入到AuthenticationManager,这意味着它已经生效。
配置属性的来源很重要,这些都是你自定义、个性化的入口。
1.4 OIDC配置
OIDC是在OAuth2的基础之上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。 Spring Security提供了OIDC相关AuthenticationProvider的支持。
类路径是否存在org.springframework.security.oauth2.jwt.JwtDecoder是开启OIDC认证的条件。
如果开启就配置OidcAuthorizationCodeAuthenticationProvider处理OIDC认证的相关逻辑;如果未开启则配置一个OidcAuthenticationRequestChecker来检查请求参数scope 是否包含openid的情况,因为scope=openid是OIDC认证的标识,表示你使用的是OIDC而非OAuth2。
OAuth2LoginAuthenticationProvider或者OidcAuthenticationRequestChecker一旦初始化,也将通过http.authenticationProvider方法加入到AuthenticationManager即时生效。
1.5 OAuth2 页面配置过滤器
如果没有自定义OAuth2页面的话才会配置OAuth2页面生成过滤器。
从SharedObjects中获取DefaultLoginPageGeneratingFilter进行了一些配置,可定制化的程度不高就不细说了。
2、configure方法

2.1 初始化并配置OAuth2AuthorizationRequestRedirectFilter
OAuth2AuthorizationRequestRedirectFilter的初始化和配置在configure阶段完成,并在完成配置后通过HttpSecurity.addFilter方法加入过滤器链。
初始化
是否存在自定义OAuth2AuthorizationRequestResolver(下面称Resolver)决定着如何初始化OAuth2AuthorizationRequestRedirectFilter。相关代码片段如下:
- 自定义Resolver的优先级最高,否则就使用默认Resolver。
这里有一个隐含的问题,如果自定义,那么通过AuthorizationEndpointConfig.baseUri配置的authorizationRequestBaseUri就废了。OAuth2AuthorizationRequestRedirectFilter本身并不对HttpServletRequest进行匹配,它会拦截所有能进入它的URL,因此在你自定义Resolver的时候一定要实现AntPathRequestMatcher来匹配URL。
- 其它配置
其它还有额外两个可选的配置:
如果我们自定义了AuthorizationRequestRepository的话,也会在这个阶段装配进OAuth2AuthorizationRequestRedirectFilter。SharedObjects中如果存在请求缓存对象RequestCache的话,就把该对象实例装配到OAuth2AuthorizationRequestRedirectFilter。 OAuth2AuthorizationRequestResolver参见OAuth2AuthorizationRequestRedirectFilter的详解。
2.2 补充配置OAuth2LoginAuthenticationFilter
OAuth2LoginAuthenticationFilter在init方法中初始化,不过并没有直接加入过滤器链。在configurer中会进一步进行配置。
- 如果通过RedirectionEndpointConfig.baseUri自定义了拦截器处理URL,会替换掉默认的/login/oauth2/code/*。
- 和OAuth2AuthorizationRequestRedirectFilter一样,如果存在自定义的AuthorizationRequestRepository,也会装配到OAuth2LoginAuthenticationFilter中。
不过OAuth2LoginAuthenticationFilter并没有在OAuth2LoginConfigurer中直接加入过滤器链,因为它还没有配置完善。‘’
2.3 执行父类的configure方法
最后OAuth2LoginConfigurer.configure会调用父类AbstractAuthenticationFilterConfigurer的configure方法。在父类的configure方法中OAuth2LoginAuthenticationFilter进一步完善配置并最终加入过滤器链。
以上就是父类的configure方法配置属性的图谱,这些属性一部分是通过默认值,一部分是通过SharedObjects。
这里看完后最好回顾一下微信OAuth2授权登录相关的自定义配置项,结合本文涉及的知识点加深印象。
OAuth2 Login讲完了,还有一个OAuth2ClientConfigurer,它是HttpSecurity.oauth2Client()配置的底层逻辑。
三、OAuth2 Client 与 OAuth2 Login
OAuth2 Login都是OAuth2授权码授权模式的流程。但是它们也有不一样的地方:
- OAuth2 Login授权服务器向浏览器(User Agent)下发的302重定向到redirect_uri请求,然后OAuth2LoginAuthenticationFilter拦截redirect_uri后向授权服务器请求token和OAuth2用户信息,完成用户认证。最后重定向到登录成功路径/或者RequstCache缓存的路径,这里redirect_uri充当中转站的角色。
- OAuth2 Client是在授权服务器向浏览器(User Agent)下发的302重定向到redirect_uri请求时,被OAuth2AuthorizationCodeGrantFilter拦截后向授权服务器请求token,不会去拿OAuth2用户信息,实际是匿名用户(非认证用户),拿到token后完成redirect_uri的重定向,这里redirect_uri是最终的目的地。
OAuth2 Client配置下的redirect_uri一般是第三方的URL。
四、OAuth2ClientConfigurer

对应OAuth2LoginConfigurer,这个是用来配置OAuth2 Client的。配置两个拦截器,一个是同样配置到OAuth2LoginConfigurer中的OAuth2AuthorizationRequestRedirectFilter;另一个是上面提到的OAuth2AuthorizationCodeGrantFilter。
它的配置都委托给了AuthorizationCodeGrantConfigurer。因此我们只需要看AuthorizationCodeGrantConfigurer的逻辑即可。
1、AuthorizationCodeGrantConfigurer

前两件事参考OAuth2LoginConfigurer和OAuth2 Login相关的就可以了,我们重点放在OAuth2AuthorizationCodeGrantFilter上。
1.1 OAuth2AuthorizationCodeGrantFilter
OAuth2AuthorizationCodeGrantFilter的配置项也都是“老熟人”。它的构造包含了三个参数:
- ClientRegistrationRepository 优先从SharedObjects提取,没有就从Spring IoC中获取。
- OAuth2AuthorizedClientRepository 优先从SharedObjects提取,没有就从Spring IoC中获取,再没有就初始化一个AuthenticatedPrincipalOAuth2AuthorizedClientRepository。
- AuthenticationManager 只能从SharedObjects提取。
还有AuthorizationRequestRepository、RequestCache这两个参数保持和OAuth2AuthorizationRequestRedirectFilter一致。
和OAuth2 Login不一样的是OAuth2AuthorizationCodeGrantFilter的流程不涉及用户信息OAuth2User的获取,这也是为什么本篇DEMO是最后是匿名用户的原因。
小结
本章的东西比较简单,明白Spring Security中的OAuth2 Client和OAuth2 Login的区别和联系就可以了。它的场景主要是通过OAuth2授权才能访问的接口或者页面。
边栏推荐
- pomerium
- HCIP第十一天比较(BGP的配置、发布)
- 如何构建以客户为中心的产品蓝图:来自首席技术官的建议
- 终极套娃 2.0 | 云原生交付的封装
- This article explains the FS file module and path module in nodejs in detail
- LeetCode 263.丑数
- 华为机考 ~ 偏移量实现字符串加密
- JSON数据传递参数&日期型参数传递
- key&key_ Len & ref & filtered (4) - MySQL execution plan (50)
- B+ tree index use (6) leftmost principle -- MySQL from entry to proficiency (18)
猜你喜欢

Solve the problem that the remote host cannot connect to the MySQL database

One stroke problem (Chinese postman problem)

学习pinia 介绍-State-Getters-Actions-Plugins

【上位机教程】CANopen通信下一体化步进电机与台达PLC(AS228T)的应用

12 brand management of commodity system in gulimall background management

Detailed explanation of factory mode

【C语言学习者必会的题目集锦1】巩固基础,稳步提高

Emotion analysis model based on Bert

Kubelet CRI 容器运行时

Flutter multi-channel packaging operation
随机推荐
JVM: what does the class loading subsystem do? What is it made of? What eight part essay do you need to remember?
We were tossed all night by a Kong performance bug
key&key_len&ref&filtered(4)—mysql执行计划(五十)
Codeforces Round #810 (Div. 2)【比赛记录】
Mysql数据目录(3)---表数据结构myISAM(二十六)
Chat system based on webrtc and websocket
概要设计说明书
Kubernetes APIServer 限流策略
panic: Error 1045: Access denied for user ‘root‘@‘117.61.242.215‘ (using password: YES)
Kubelet CRI 容器运行时
[upper computer tutorial] Application of integrated stepping motor and Delta PLC (as228t) under CANopen communication
B+ tree index use (6) leftmost principle -- MySQL from entry to proficiency (18)
B+树索引使用(9)分组、回表、覆盖索引(二十一)
AI theory knowledge map 1 Foundation
目标检测网络R-CNN 系列
基于Locust框架进行文件上传下载性能测试
详解关系抽取模型 CasRel
LeetCode 217. 存在重复元素
Abstract factory and its improvement examples
Kubernetes apiserver current limiting strategy