1. 前言
在上一篇 Spring Security 实战干货:OAuth2授权回调的核心认证流程 中,我们讲了当第三方同意授权后会调用 redirectUri
发送回执给我们的服务器。我们的服务器拿到一个中间授信凭据会再次进行认证,目的是为了获取 Token 。而这个逻辑由 OAuth2LoginAuthenticationProvider
负责,经过 上一文 的分析后我们发现获取 Token 的具体逻辑由 OAuth2AuthorizationCodeAuthenticationProvider
来完成,今天就把它的流程搞清楚,来看看 Spring Security OAuth2 认证授权获取 Token 的具体步骤。
注意:本 Spring Security 干货系列教程的OAuth2相关部分是在 Spring Security 5.x 版本的。
2. OAuth2AuthorizationCodeAuthenticationProvider
该类是 AuthenticationProvider
针对 OAuth 2.0 中 Authorization Code Grant 模式的实现。关于 AuthenticationProvider
有必要简单强调一下,它已经多次在 Spring Security干货系列中 出现,十分重要!一定要去看看相关的分析和使用,它是你根据业务扩展认证方式渠道的重要入口。
2.1 OAuth2AccessTokenResponseClient
在该实现中包含了一个 OAuth2AccessTokenResponseClient
成员变量,它抽象了通过 tokenUri
端点从认证服务器获取 Token 的细节。你可以根据 OAuth 2.0 常用的四种模式来进行实现它, 以达到根据不同的策略来获取 Token 的能力。
在 Spring Security 5 中 OAuth 2.0 登录的配置中默认使用 DefaultAuthorizationCodeTokenResponseClient
。如果你想使用自定义实现的话可以通过 HttpSecurity
来配置:
@Override protected void configure(HttpSecurity http) throws Exception { http.oauth2Login() .tokenEndpoint() // 注入自定义的 OAuth2AccessTokenResponseClient .accessTokenResponseClient(authorizationCodeTokenResponseClient); // 其它省略 }
接下来我们看看 DefaultAuthorizationCodeTokenResponseClient
实现的获取 Token 的逻辑:
@Override public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { Assert.notNull(authorizationCodeGrantRequest, "authorizationCodeGrantRequest cannot be null"); // 1. 封装调用tokenUri所需要的请求参数RequestEntity RequestEntity<?> request = this.requestEntityConverter.convert(authorizationCodeGrantRequest); ResponseEntity<OAuth2AccessTokenResponse> response; try { // 2. 通过RestTemplate 发起请求获取 OAuth2AccessTokenResponse response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); } catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); throw new OAuth2AuthorizationException(oauth2Error, ex); } // 3. 解析 ResponseEntity 组织返回值 OAuth2AccessTokenResponse OAuth2AccessTokenResponse tokenResponse = response.getBody(); if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) { // originally requested by the client in the Token Request tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) .scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes()) .build(); } return tokenResponse; }
这里的方式跟我另一个开源项目 Payment Spring Boot 的请求方式异曲同工,都是三个步骤:
RequestEntity RestOperations ResponseEntity
如果有些的 OAuth 2.0 认证服务器获取 Token 的方式比较特殊你可以自行实现 OAuth2AccessTokenResponseClient
。
3. 总结
OAuth2AccessTokenResponseClient
是 OAuth2AuthorizationCodeAuthenticationProvider
的核心要点。搞清楚它的作用和机制就可以了。这里我们总结一下 OAuth2AuthorizationCodeAuthenticationProvider
的认证过程:
- 检测未授信
OAuth2AuthorizationCodeAuthenticationToken
的状态是否合法。 - 通过
OAuth2AccessTokenResponseClient
请求 OAuth 2.0 认证服务器获取 Token 等信息。 - 组装认证过的授信
OAuth2AuthorizationCodeAuthenticationToken
返回。
到此 OAuth 2.0 的登录流程就搞清楚了,读者可通过系列文章进行学习批判。我是: 码农小胖哥 ,多多关注,获取实用的编程干货。
关注公众号:Felordcn 获取更多资讯