当前位置:网站首页>【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授权才能访问的接口或者页面。
边栏推荐
- B+树挑选索引(1)---mysql从入门到精通(二十二)
- Analysis on the current situation and optimization strategy of customer experience management in banking industry
- (Reprint) creation methods of various points in ArcGIS Engine
- 概率论与数理统计
- JVM: what does the class loading subsystem do? What is it made of? What eight part essay do you need to remember?
- Use grid to realize left, middle and right layout, and the middle content is adaptive
- Kubelet CRI 容器运行时
- MySQL data directory (2) -- table data structure (XXV)
- Streamnational team culture: a "transparent" company
- B+ tree (4) joint index -- MySQL from entry to proficiency (16)
猜你喜欢

解决远程主机无法连接mysql数据库的问题
![[5gc] what is 5g slice? How does 5g slice work?](/img/8c/52ba57d6a18133e97fa00b6a7cf8bc.png)
[5gc] what is 5g slice? How does 5g slice work?

One stroke problem (Chinese postman problem)
![[typescript] typescript common types (Part 1)](/img/80/5c8c51b92d3a9d76f38beba7be0aa6.png)
[typescript] typescript common types (Part 1)

详解关系抽取模型 CasRel

With 8 years of product experience, I have summarized these practical experience of continuous and efficient research and development

Kubelet CRI container runtime

Kubernetes APIServer 限流策略

Kubernetes flannel: host-gw mode

天津市应急局与驻津央企签署协议深化应急联动机制建设
随机推荐
多线程使用不当导致的 OOM
B+树(5)myISAM简介 --mysql从入门到精通(十七)
同站攻击(相关域攻击)论文阅读 Can I Take Your Subdomain?Exploring Same-Site Attacks in the Modern Web
B+树挑选索引(1)---mysql从入门到精通(二十二)
[flower carving hands-on] interesting and fun music visualization series small project (13) -- organic rod column lamp
B+ tree selection index (2) -- MySQL from entry to proficiency (23)
银行业客户体验管理现状与优化策略分析
How to face scientific and technological unemployment?
从其他文件触发pytest.main()注意事项
基于ASP.NET的某高校学院档案管理系统
异步线程池在开发中的使用
Reflection, an implementation of automatic repeated call interface
Solve the problem that the remote host cannot connect to the MySQL database
Hcip day 12 notes sorting (BGP Federation, routing rules)
Golang端口扫描设计
基于Locust框架进行文件上传下载性能测试
Is the account opened by flush safe?
Photoshop(CC2020)未完
7-25 0-1 backpack (50 points)
AI theory knowledge map 1 Foundation