zoukankan      html  css  js  c++  java
  • 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-methodnone时上述四个参数:

    {
      "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-methodnone时上述四个参数:

    {
      "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等参数来生成,稍后会把构造机制分析一波。
    • redirectUriOAuth2AuthorizationRequest被第三方平台收到后,第三方平台会回调这个URI来对授权请求进行相应,稍后也会来分析其机制。

    authorizationRequestUri的构建机制

    如果不显式提供authorizationRequestUri就会通过OAuth2AuthorizationRequest中的

    • responseType
    • clientId
    • scopes
    • state
    • redirectUri
    • additionalParameters

    按照下面的规则进行拼接成authorizationUri的参数串,参数串的keyvalue都要进行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,有两种默认值loginauthorize ,当/oauth2/authorization请求中包含了action参数时会根据action的值进行填充。
    • registrationId 这个就不用多说了。

    4. 总结

    通过对OAuth2AuthorizationRequest请求对象的规则进行详细分析,我们应该能大致的知道的过滤器OAuth2AuthorizationRequestRedirectFilter流程:

    1. 通过客户端配置构建ClientRegistration,后续可以进行持久化。
    2. 拦截/oauth2/authorization请求并构造OAuth2AuthorizationRequest,然后重定向到authorizationRequestUri进行请求授权。
    3. 第三方通过redirect_uri进行相应。

    那么Spring Security OAuth2如何对第三方的回调相应进行处理呢?关注:码农小胖哥 为你揭晓这个答案。

    关注公众号:Felordcn 获取更多资讯

    个人博客:https://felord.cn

  • 相关阅读:
    Distribution(F题)---第八届河南省程序设计大赛
    河南省省赛总结
    Wireless Network--poj2236(并查集)
    River Crossing---河南省第六届大学生程序设计竞赛
    Monkey and Banana---hdu1069(dp)
    Bone Collector--hdu2602(01背包)
    节能--河南省第六届大学生程序设计竞赛
    最舒适的路线--河南省第六届大学生程序设计竞赛
    MPEG2简单码流分析
    H.264简单码流分析
  • 原文地址:https://www.cnblogs.com/felordcn/p/13957001.html
Copyright © 2011-2022 走看看