Spring Security 实战干货:OAuth2授权请求是如何构建并执行的
在Spring Security 实战干货:客户端OAuth2授权请求的入口中我们找到了拦截OAuth2授权请求入口/oauth2/authorization
的过滤器OAuth2AuthorizationRequestRedirectFilter
,并找到了真正发起OAuth2授权请求的方法sendRedirectForAuthorization
。但是这个方法并没有细说,所以今天接着上一篇把这个坑给补上。
2. sendRedirectForAuthorization
这个sendRedirectForAuthorization
方法没多少代码,它的主要作用就是向第三方平台进行授权重定向访问。它所有的逻辑都和OAuth2AuthorizationRequest
有关,因此我们对OAuth2AuthorizationRequest
进行轻描淡写是不行的,我们必须掌握OAuth2AuthorizationRequest
是怎么来的,干嘛用的。
OAuth2AuthorizationRequestResolver
这就需要去分析解析类OAuth2AuthorizationRequestResolver
,其核心方法有两个重载,这里分析一个就够了。
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
// registrationId是通过uri路径参数/oauth2/authorization/{registrationId}获得的
String registrationId = this.resolveRegistrationId(request);
// 然后去请求对象request中提取key为action的参数,默认值是login
String redirectUriAction = getAction(request, "login");
// 然后进入根本的解析方法
return resolve(request, registrationId, redirectUriAction);
}
上面方法里面的resolve(request, registrationId, redirectUriAction)
方法才是最终从/oauth2/authorization
提取OAuth2AuthorizationRequest
的根本方法。代码太多但是我尽量通俗易懂的来进行图解。resolve
方法会根据不同的授权方式(AuthorizationGrantType
)来组装不同的OAuth2AuthorizationRequest
。
3. OAuth2AuthorizationRequest
接下来就是OAuth2.0协议的核心重中之重了,可能以后你定制化的参考就来自这里,这是圈起来要考的知识点。我会对OAuth2AuthorizationRequestResolver
在各种授权方式下的OAuth2AuthorizationRequest
对象的解析进行一个完全的总结归纳。大致分为以下两部分:
3.1 由AuthorizationGrantType决定的
在不同AuthorizationGrantType
下对OAuth2AuthorizationRequest
的梳理。涉及到的成员变量有:
authorizationGrantType
,来自配置spring.security.client.registration.{registrationId}.authorizationGrantType
。responseType
, 由authorizationGrantType
的值决定,参考下面的JSON。additionalParameters
,当authorizationGrantType
值为authorization_code
时需要额外的一些参数,参考下面JSON 。attributes
,不同的authorizationGrantType
存在不同的属性。
其中类似
{registrationId}
的形式表示{registrationId}
是一个变量,例如registrationId=gitee
。
在OAuth2客户端配置spring.security.client.registration.{registrationId}
的前缀中有以下五种情况。
当 scope
不包含openid
而且client-authentication-method
不为none
时上述四个参数:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {},
"attributes": {
"registration_id": "{registrationId}"
}
}
当 scope
包含openid
而且client-authentication-method
不为none
时上述四个参数:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"nonce": "{nonce}的Hash值"
},
"attributes": {
"registration_id": "{registrationId}",
"nonce": "{nonce}"
}
}
当 scope
不包含openid
而且client-authentication-method
为none
时上述四个参数:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"code_challenge": "{codeVerifier}的Hash值",
// code_challenge_method 当不是SHA256可能没有该key
"code_challenge_method": "S256(如果是SHA256算法的话)"
},
"attributes": {
"registration_id": "{registrationId}",
"code_verifier": "Base64生成的安全{codeVerifier}"
}
}
当 scope
包含openid
而且client-authentication-method
为none
时上述四个参数:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"code_challenge": "{codeVerifier}的Hash值",
// code_challenge_method 当不是SHA256可能没有该key
"code_challenge_method": "S256(如果是SHA256算法的话)",
"nonce": "{nonce}的Hash值"
},
"attributes": {
"registration_id": "{registrationId}",
"code_verifier": "Base64生成的安全{codeVerifier}",
"nonce": "{nonce}"
}
}
implicit
下要简单的多:
{
"authorizationGrantType": "implicit",
"responseType": "token",
"attributes": {}
}
3.2 固定规则部分
上面是各种不同AuthorizationGrantType
下的OAuth2AuthorizationRequest
的成员变量个性化取值策略, 还有几个参数的规则是固定的:
clientId
来自于配置,是第三方平台给予我们的唯一标识。authorizationUri
来自于配置,用来构造向第三方发起的请求URL。scopes
来自于配置,是第三方平台给我们授权划定的作用域,可以理解为角色。state
自动生成的,为了防止csrf 攻击。authorizationRequestUri
向第三方平台发起授权请求的,可以直接通过OAuth2AuthorizationRequest
的构建类来设置或者通过上面的authorizationUri
等参数来生成,稍后会把构造机制分析一波。redirectUri
当OAuth2AuthorizationRequest
被第三方平台收到后,第三方平台会回调这个URI来对授权请求进行相应,稍后也会来分析其机制。
authorizationRequestUri的构建机制
如果不显式提供authorizationRequestUri
就会通过OAuth2AuthorizationRequest
中的
responseType
clientId
scopes
state
redirectUri
additionalParameters
按照下面的规则进行拼接成authorizationUri
的参数串,参数串的key
和value
都要进行URI编码。
authorizationUri?response_type={responseType.getValue()}&client_id={clientId}&scope={scopes元素一个字符间隔}&state={state}&redirect_uri={redirectUri}&{additionalParameter展开进行同样规则的KV参数串}
然后OAuth2AuthorizationRequestRedirectFilter
负责重定向到authorizationRequestUri
向第三方请求授权。
redirectUri
第三方收到响应会调用redirectUri
,回调也是有一定默认规则的,它遵循{baseUrl}/{action}/oauth2/code/{registrationId}
的路径参数规则。
baseUrl
是从我们/oauth2/authorization
请求中提取的基础请求路径。action
,有两种默认值login
、authorize
,当/oauth2/authorization
请求中包含了action
参数时会根据action
的值进行填充。registrationId
这个就不用多说了。
4. 总结
通过对OAuth2AuthorizationRequest
请求对象的规则进行详细分析,我们应该能大致的知道的过滤器OAuth2AuthorizationRequestRedirectFilter
流程:
- 通过客户端配置构建
ClientRegistration
,后续可以进行持久化。 - 拦截
/oauth2/authorization
请求并构造OAuth2AuthorizationRequest
,然后重定向到authorizationRequestUri
进行请求授权。 - 第三方通过
redirect_uri
进行相应。
那么Spring Security OAuth2如何对第三方的回调相应进行处理呢?关注:码农小胖哥
为你揭晓这个答案。
关注公众号:Felordcn 获取更多资讯
Spring Security 实战干货:OAuth2授权请求是如何构建并执行的的更多相关文章
- Spring Security 实战干货:客户端OAuth2授权请求的入口
1. 前言 在Spring Security 实战干货:OAuth2第三方授权初体验一文中我先对OAuth2.0涉及的一些常用概念进行介绍,然后直接通过一个DEMO来让大家切身感受了OAuth2.0第 ...
- Spring Security 实战干货:OAuth2第三方授权初体验
1. 前言 Spring Security实战干货系列 现在很多项目都有第三方登录或者第三方授权的需求,而最成熟的方案就是OAuth2.0授权协议.Spring Security也整合了OAuth2. ...
- Spring Security 实战干货: 简单的认识 OAuth2.0 协议
1.前言 欢迎阅读 Spring Security 实战干货 系列文章 .OAuth2.0 是近几年比较流行的授权机制,对于普通用户来说可能每天你都在用它,我们经常使用的第三方登录大都基于 OAuth ...
- Spring Security 实战干货:OAuth2登录获取Token的核心逻辑
1. 前言 在上一篇Spring Security 实战干货:OAuth2授权回调的核心认证流程中,我们讲了当第三方同意授权后会调用redirectUri发送回执给我们的服务器.我们的服务器拿到一个中 ...
- Spring Security 实战干货:图解Spring Security中的Servlet过滤器体系
1. 前言 我在Spring Security 实战干货:内置 Filter 全解析对Spring Security的内置过滤器进行了罗列,但是Spring Security真正的过滤器体系才是我们了 ...
- Spring Security 实战干货:使用 JWT 认证访问接口
(转载)原文链接:https://my.oschina.net/10000000000/blog/3127268 1. 前言 欢迎阅读Spring Security 实战干货系列.之前我讲解了如何编写 ...
- Spring Security 实战干货:理解AuthenticationManager
1. 前言 我们上一篇介绍了UsernamePasswordAuthenticationFilter的工作流程,留下了一个小小的伏笔,作为一个Servlet Filter应该存在一个doFilter实 ...
- Spring Security 实战干货:图解用户是如何登录的
1. 前言 欢迎阅读Spring Security 实战干货系列文章,在集成Spring Security安全框架的时候我们最先处理的可能就是根据我们项目的实际需要来定制注册登录了,尤其是Http登录 ...
- Spring Security 实战干货:实现自定义退出登录
文章目录 1. 前言 2. 我们使用 Spring Security 登录后都做了什么 2. 退出登录需要我们做什么 3. Spring Security 中的退出登录 3.1 LogoutFilte ...
随机推荐
- trie树——【吴传之火烧连营】
突然发现好像没有讲过一种叫做tire树的神奇东西. 问题描述: 题目描述 [题目背景] 蜀汉章武元年(221年),刘备为报吴夺荆州.关羽被杀之仇,率大军攻吴.吴将陆逊为避其锋,坚守不战,双方成对峙之势 ...
- 小程序将base64的多张图片,传到tp5后台
zhu要是前端传过来的数据是base64的数据库存储不了base64的数据,因存储量太过于大,因此后台要将base64的数据转换成,34124323534.jpg等格式的,数据库才可将其存储 源码暂时 ...
- 例题3-3 回文词(Palindromes, UVa401)
输入一个字符串,判断它是否为回文串以及镜像串.输入字符串保证不含数字0.所谓 回文串,就是反转以后和原串相同,如abba和madam.所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE.注意, ...
- redhat系统服务器重启后提示An error occurred during the file system check.
问题描述 浪潮一台NF8480M3外观红灯报警,鉴于无法登陆带外,只能对服务器进行断电重启操作 问题现象 重启后进入开机过程并报错,报错如下内容及图片如下所示,正常来说进入此界面后直接输入root密码 ...
- 转 mysql show processlist 查看当前连接
show processlist和show full processlist processlist命令的输出结果显示了有哪些线程在运行,不仅可以查看当前所有的连接数,还可以查看当前的连接状态帮助识别 ...
- spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)
一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...
- php 注册器模式 工厂模式
<?php /** * 注册器模式 * 全局共享和交换对象 */ class Register { public static $objects; // 定义全局数组 // 保存对象到全局数组 ...
- xpath取其中几个使用position
from lxml import etree html = ''' <!DOCTYPE html> <html lang="en"> <head> ...
- Gitlab 11.9.1 高可用教程
Gitlab 11.9.1 高可用教程 一. PostgreSQL数据迁移 由于默认Gitlab的安装会内置Postgres数据库,并且没有对外,所以我们需要通过设置对应的Gitlab的配置将其中的数 ...
- Linux安装软件时90%的人会遇到这个报错,如何解决?
提示 Could not get lock /var/lib/dpkg/lock 报错? 有些小伙伴在使用 apt 包管理器更新或安装软件时,可能会遇到过诸如以下的错误提示: E: Could not ...