zoukankan      html  css  js  c++  java
  • 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的能力。

    OAuth 2.0 四种模式的对应实现

    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的请求方式异曲同工,都是三个步骤:

    1. 组织参数RequestEntity
    2. RestOperations发起请求。
    3. 解析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

    博主:码农小胖哥
    出处:felord.cn
    本文版权归原作者所有,不可商用,转载需要声明出处,否则保留追究法律责任的权利。如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    循环链表结构
    复杂的权衡之时间、空间和单链表结构
    单链表操作之删除
    单链表操作之插入
    单链表操作之替换
    单链表操作之搜索
    文件系统的原理
    类加载的三种方式比较
    shell中awk printf的用法
    推荐网站
  • 原文地址:https://www.cnblogs.com/felordcn/p/14434677.html
Copyright © 2011-2022 走看看