Spring Security OAuth2 完全解析 (流程/原理/实战定制) —— Client / ResourceServer 篇 (2)

OAuth2AuthenticationToken
authenticated=true 认证后安全上下文实际保存的OAuth2用户认证,由convert将填充后的OAuth2LoginAuthenticationToken转换而来。

5. 相关 Filter

Spring Security OAuth2 完全解析 (流程/原理/实战定制) —— Client / ResourceServer 篇

OAuth2AuthorizationRequestRedirectFilter

通过调用OAuth2AuthorizationRequestResolver用于判断是否为授权请求(默认为 "/oauth2/authorization/{registrationId}",可通过.oauth2Login().authorizationEndpoint().baseUri()配置) ,并且请求包装为OAuth2AuthorizationRequest后由authorizationRequestRepository(默认基于SESSION实现)将授权请求保存(后有他用)

随后重定向到追加了参数(client-id、response_type)的真实授权码请求。

OAuth2LoginAuthenticationFilter
继承自AbstractAuthenticationProcessingFilter,即负责身份认证的Filter。

当是loginProcessingUrl(默认为/login/oauth2/code/*)请求且带了code和state时,尝试以这俩参数构建OAuth2LoginAuthenticationToken且调用AuthenticationManager去进行认证。

认证通过后,调用authenticationResultConverter将认证后完全填充的OAuth2LoginAuthenticationToken转为authenticated=true的OAuth2AuthenticationToken,用以代表认证后的身份。(该converter默认就是直接提取填充后的"principal、authorities、clientid"直接new)

将先前得到 "token、refreshToken" 等信息包装为OAuth2AuthorizedClient调用 OAuth2AuthorizedClientRepository#saveAuthorizedClient保存起来(默认是基于内存实现的ClientId和Principal为key的Map)

OAuth2AuthorizationCodeGrantFilter
(该Filter,在oauth2Login()下会永远被跳过,因为该请求已被OAuth2LoginAuthenticationFilter处理后通过successHandler重定向)
匹配带code与state的请求(表示回调请求)且满足authorizationRequestRepository.loadAuthorizationRequest不为空时(表示经过了RedirectFilter,是先前授权请求发起的),会构造 OAuth2AuthorizationCodeAuthenticationToken交由AuthenticationManager(背后交由OAuth2AuthorizationCodeAuthenticationProvider)进行认证,并将结果构造为OAuth2AuthorizedClient交由authorizedClientRepository保存,然后去除参数再将请求重定向到 "savedRequest 或者 redirect-url"。
【注:不是很能理解该Filter这里为什么要重定向,这个重定向真的很恼火。如果API自身需要code,这重定向把参数清除了会报错;而即便API不要code了依附于它的逻辑使用authorizedClientRepository,那也是无意义多一次请求。而且其基于SESSION的实现本来没什么问题,但非要重定向请求一次就导致单纯的多实例时会存在问题】

6. 相关 Provider

OAuth2LoginAuthenticationProvider

对OAuth2LoginAuthenticationToken尝试认证,其内会进一步构造OAuth2AuthorizationCodeAuthenticationToken,然后调用 OAuth2AuthorizationCodeAuthenticationProvider 对其进行认证。

经过上述认证后拿到填充了 "access_token" 的OAuth2AuthorizationCodeAuthenticationToken,会构造成OAuth2UserRequest后传给OAuth2UserService负责进行实际的 "user-info-uri" 请求,并将结果包装成DefaultOAuth2User返回。(该User拥有两类authorities,一个是ROLE_USER(Spring在经过oauth2UserService时手动添加的),一类是Token中的SCOPE_{sopces})

Spring Security OAuth2 完全解析 (流程/原理/实战定制) —— Client / ResourceServer 篇

OAuth2AuthorizationCodeAuthenticationProvider
对OAuth2AuthorizationCodeAuthenticationToken尝试认证,内部会构造对"token-uri"的实际请求,并调用DefaultAuthorizationCodeTokenResponseClient进行请求返回,并根据返回结果OAuth2AccessTokenResponse(内含access_token/refreash_token),新new一个填充了"access_token"的OAuth2AuthorizationCodeAuthenticationToken返回。

四、oauth2ResourceServer 1. 概述

由 org.springframework.boot:spring-boot-starter-oauth2-resource-server 引入,提供对请求中携带token校验解析、身份认证的服务。

2. 必须的配置

JwtDecoder:在oauth2ResourceServer的Configurer::init时,会构建JwtAuthenticationProvider,它就需要decorder以提供对"token"校验解析。

JwtEncoder:虽然不是必须的,但我们自己系统登录有令牌分发的需要。

3. 相关 Filter

BearerTokenAuthenticationFilter
(虽没继承AbstractAuthenticationProcessingFilter但却干着认证的事)
首先通过DefaultBearerTokenResolver::resolve判断是否含"token",然后构建BearerTokenAuthenticationToken并调用AuthenticationManager尝试认证。
将认证后的结果JwtAuthenticationToken设置到安全上下文中。如果中途出现了异常,则以该filter的authenticationEntryPoint(可通过.oauth2ResourceServer().authenticationEntryPoint配置) 处理。

4. 相关 Authentication

BearerTokenAuthenticationToken
代表原始token的一个过渡身份。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzywyj.html