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

  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

Spring Security 实战干货:OAuth2登录获取Token的核心逻辑的更多相关文章

  1. Spring Security 实战干货:使用 JWT 认证访问接口

    (转载)原文链接:https://my.oschina.net/10000000000/blog/3127268 1. 前言 欢迎阅读Spring Security 实战干货系列.之前我讲解了如何编写 ...

  2. Spring Security 实战干货: 简单的认识 OAuth2.0 协议

    1.前言 欢迎阅读 Spring Security 实战干货 系列文章 .OAuth2.0 是近几年比较流行的授权机制,对于普通用户来说可能每天你都在用它,我们经常使用的第三方登录大都基于 OAuth ...

  3. Spring Security 实战干货:图解用户是如何登录的

    1. 前言 欢迎阅读Spring Security 实战干货系列文章,在集成Spring Security安全框架的时候我们最先处理的可能就是根据我们项目的实际需要来定制注册登录了,尤其是Http登录 ...

  4. Spring Security 实战干货:实现自定义退出登录

    文章目录 1. 前言 2. 我们使用 Spring Security 登录后都做了什么 2. 退出登录需要我们做什么 3. Spring Security 中的退出登录 3.1 LogoutFilte ...

  5. Spring Security 实战干货:如何实现不同的接口不同的安全策略

    1. 前言 欢迎阅读 Spring Security 实战干货 系列文章 .最近有开发小伙伴提了一个有趣的问题.他正在做一个项目,涉及两种风格,一种是给小程序出接口,安全上使用无状态的JWT Toke ...

  6. Spring Security 实战干货:图解Spring Security中的Servlet过滤器体系

    1. 前言 我在Spring Security 实战干货:内置 Filter 全解析对Spring Security的内置过滤器进行了罗列,但是Spring Security真正的过滤器体系才是我们了 ...

  7. Spring Security 实战干货:理解AuthenticationManager

    1. 前言 我们上一篇介绍了UsernamePasswordAuthenticationFilter的工作流程,留下了一个小小的伏笔,作为一个Servlet Filter应该存在一个doFilter实 ...

  8. Spring Security 实战干货:从零手写一个验证码登录

    1. 前言 前面关于Spring Security写了两篇文章,一篇是介绍UsernamePasswordAuthenticationFilter,另一篇是介绍 AuthenticationManag ...

  9. Spring Security 实战:QQ登录实现

    准备工作 1.在 QQ互联 申请成为开发者,并创建应用,得到APP ID 和 APP Key.2.了解QQ登录时的 网站应用接入流程.(必须看完看懂) 为了方便各位测试,直接把我自己申请的贡献出来:A ...

  10. Spring Security之多次登录失败后账户锁定功能的实现

    在上一次写的文章中,为大家说到了如何动态的从数据库加载用户.角色.权限信息,从而实现登录验证及授权.在实际的开发过程中,我们通常会有这样的一个需求:当用户多次登录失败的时候,我们应该将账户锁定,等待一 ...

随机推荐

  1. 《UML大战需求分析》阅读随笔(六)

    在我们做的代码设计中分为系统设计和程序设计.程序设计是系统设计中模拟程序的执行逻辑,定义客户机服务器对象合作的框架的那个部分.程序和事务设计中,作者讲述到程序和事务设计将系统设计制品放在一起,并作为系 ...

  2. AssetBundle系列——游戏资源打包(二)

    本篇接着上一篇.上篇中说到的4步的代码分别如下所示: (1)将资源打包成assetbundle,并放到自定目录下 using UnityEditor; using UnityEngine; using ...

  3. 二十四种设计模式:组合模式(Composite Pattern)

    组合模式(Composite Pattern) 介绍将对象组合成树形结构以表示"部分-整体"的层次结构.它使得客户对单个对象和复合对象的使用具有一致性.示例有一个Message实体 ...

  4. 转 在SQL Server中创建用户角色及授权(使用SQL语句)

     目录 要想成功访问 SQL Server 数据库中的数据 我们需要两个方面的授权 完整的代码示例 使用存储过程来完成用户创建 实例 要想成功访问 SQL Server 数据库中的数据, 我们需要两个 ...

  5. NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.

    解决办法: http://stackoverflow.com/questions/4037125/namespace-err-an-attempt-is-made-to-create-or-chang ...

  6. jtree(选择框)

    jtree一般的用法是: 1. 展示电脑中文件的层次结构,如图所示. 具体的代码: package jtree; import java.io.File; import javax.swing.JTr ...

  7. 通过浏览器直接打开Android应用程序

    需求 通过手机浏览器直接打开Android应用程序.假设本地已经安装了指定Android应用,就直接打开它:假设没有安装,则直接下载该应用的安装文件(也能够跳转到下载页面). 实现效果 假设手机上已经 ...

  8. 使用bootstrap的插件实现模态框效果

    在上一篇文章中,我们使用 js+css 实现了模态框效果,在理解了模态框的基本实现方法和实现效果后,我们就要寻找更快捷的方法,又快又好的来完成模态框开发需求,从而节约时间,提高效率.一个好的轮子,不仅 ...

  9. Coin Change (IV) (dfs)

    Coin Change (IV) Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu [Subm ...

  10. Windows系统重装

    http://www.ishuo.cn/show/76437.htmlhttp://jingyan.baidu.com/article/d8072ac45d4f60ec95cefdaa.html