本文假设读者对 Spring Security 本身原理有一定程度的了解,假设对 OAuth2 规范流程、Jwt 有基础了解,以此来对 SpringSecurity 整合 OAuth2 有个快速全面的认识。
(关于总体流程,若对SS实在不熟悉可以简单理解为:Filter构造Authentication-> Provider认证并填充-> 设置到SecurityContext -> 而后用于Filter/AOP鉴权)
要了解一个SpringSecurity模块,就是了解它如何身份认证、如何自定义、(至于如何鉴权是SpringSecurity通用部分),对应到代码就是:背后的相关 Configurer、Filter、Authentication、Provider。
本文以最新Spring Boot版本2.6.2 按此逻辑梳理;涉及源码太多,就不放源码对照了,可以自行fork查看;斜体表示可配置自定义替换的部分
第一部分:先演示默认配置下 spring-boot-starter-oauth2-client 所带来的流程和效果,建立大概认知。对应代码 thirdpart-login 项目
第二部分:全面解析 oauth2login、oauth2client 原理。
第三部分:常见业务下我们自己用户系统也有token分发需求,因此也解读下提供JWT服务的 oauth2ResourceServer 模块
第四部分:综上所述,实战定制SpringSecurity OAuth2。对应代码 thirdpart-login-custom
二、默认 spring-boot-starter-oauth2-client 效果预览由 OAuth2ClientAutoConfiguration自动配置类引入的默认配置,可由代码 thirdpart-login 复现。
后端在 .yml 配置中做好相关配置
访问受限资源"/user",后端鉴权异常后,由LoginUrlAuthenticationEntryPoint重定向到登录页。
登录页则由DefaultLoginPageGeneratingFilter根据相关配置自动构造页面String返回。
页面点击<a "href"="/oauth2/authorization/gitee">发出授权请求。
后端OAuth2AuthorizationRequestRedirectFilter匹配响应该模板路径,返回实际授权码请求的重定向响应,转入三方授权页面:
同意授权后,Gitee会向游览器返回重定向响应。
游览器向 "redirect-uri" 发起访问,此时被后端OAuth2LoginAuthenticationFilter匹配处理,其会用请求携带的 code 向配置的 "token-uri、user-info-uri" 发起一系列请求,最后构造出认证后的身份放入SecurityContext,以SESSION持久化等。再将先前保存在SESSION中的的受限资源访问请求拿出,重定向重新访问。
这两者都是在SpringSecurity中整合OAuth2的入口方法(例http.oauth2Login()),对应OAuth2LoginConfigurer、OAuth2ClientConfigurer,只是引入Filter有所异同。简而言之:
oauth2Login会在授权请求时进行认证(即设置安全上下文SecurityContext),背后会连续访问acc_token&user-info-url 将获取的用户信息构造填充 Authentication。
而oauth2Client也会对授权请求进行处理,但只是获取到access_token后用repository存起来(要怎么使用自行处理),不会认证,这也意味着需要自行实现认证逻辑。
2. 从 OAuth2 请求的维度概览对 授权码code 的请求:由OAuth2AuthorizationRequestRedirectFilter响应"授权请求"向客户端返回重定向响应,定向到实际 "authorization-uri"
对 access_token 和 user-info-uri 实际请求:OAuth2LoginAuthenticationFilter会对回调地址(携带了code和state)进行处理,调用AuthemticationManager进行认证。背后OAuth2LoginAuthenticationProvider会进行连续 token-uri、user-info-uri 请求,最后返回完全填充的OAuth2LoginAuthenticationToken。
3. 必须要配置的属性:太长就不贴了 参考Github项目代码,CommonOAuth2Provider也内建了一些常见OAuth2提供方,在之内少配几个字段也没关系。
Client属性:OAuth2ClientRegistrationRepositoryConfiguration用以处理application.yml中的相关属性,并构建代表OAuth2方的一个个ClientRegistration。根据不同模式,对必须属性有不同要求。
provider属性:除了上图授权码模式下必须校验的 "authorization-uri、token-uri" 外,"user-info-uri"、userNameAttribute也是必须的,在后续OAuth2LoginAuthenticationProvider调用的DefaultOAuth2UserService内,必须需要这俩属性才能尝试访问 user-info-uri 并包装为DefaultOAuth2User。
4. 相关 Authentication
OAuth2LoginAuthenticationToken
用以给Provider认证过渡用,最初仅含code,最终包含access_token、user等。
OAuth2AuthorizationCodeAuthenticationToken
用以给Provider认证过渡用,未填充时仅含code,经填充后包含access_token等。