乐趣区

关于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

退出移动版