在 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 获取更多资讯
集体博客:https://felord.cn