Spring Security 实战干货:OAuth2登录获取Token的核心逻辑

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.0Authorization Code Grant 模式的实现。关于 AuthenticationProvider 有必要简单强调一下,它已经多次在 Spring Security干货系列中 出现,十分重要!一定要去看看相关的分析和使用,它是你根据业务扩展认证方式渠道的重要入口。

2.1 OAuth2AccessTokenResponseClient

在该实现中包含了一个 OAuth2AccessTokenResponseClient 成员变量,它抽象了通过 tokenUri 端点从认证服务器获取 Token 的细节。你可以根据 OAuth 2.0 常用的四种模式来进行实现它, 以达到根据不同的策略来获取 Token 的能力。

Spring Security 5OAuth 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. 总结

OAuth2AccessTokenResponseClientOAuth2AuthorizationCodeAuthenticationProvider 的核心要点。搞清楚它的作用和机制就可以了。这里我们总结一下 OAuth2AuthorizationCodeAuthenticationProvider 的认证过程:

  1. 检测未授信 OAuth2AuthorizationCodeAuthenticationToken 的状态是否合法。
  2. 通过 OAuth2AccessTokenResponseClient 请求 OAuth 2.0 认证服务器获取 Token 等信息。
  3. 组装认证过的授信 OAuth2AuthorizationCodeAuthenticationToken 返回。

到此 OAuth 2.0 的登录流程就搞清楚了,读者可通过系列文章进行学习批判。我是: 码农小胖哥 ,多多关注,获取实用的编程干货。

关注公众号:Felordcn 获取更多资讯

个人博客:https://felord.cn

博客园精华区
我还没有学会写个人说明!
上一篇

Overactive在多伦多投资5亿美元开建电子竞技新场馆

下一篇

编写高效内存Python代码的3个技巧

你也可能喜欢

评论已经被关闭。

插入图片