Spring Security 实战干货:OAuth2授权请求是如何构建并执行的
1. 前言
在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 如何对第三方的回调相应进行处理呢?关注:码农小胖哥
为你揭晓这个答案。
文章来源: felord.blog.csdn.net,作者:码农小胖哥,版权归原作者所有,如需转载,请联系作者。
原文链接:felord.blog.csdn.net/article/details/109610507
- 点赞
- 收藏
- 关注作者
评论(0)