3-OAuth2登录流程分析

在上一篇胖哥和大家共同体验了OAuth2登录流程,直观感受了OAuth2,本篇我们来共同分析一下OAuth2登录的流程,本次分析将严重依赖trace日志。

流程分析

①访问被拒绝

/foo/hello发起请求后会经过一系列过滤器链的过滤触发访问被拒绝,核心的日志如下:
在这里插入图片描述

  1. 进入HTTP资源安全处理过滤器FilterSecurityInterceptor
  2. 发现本次/foo/hello请求是一个匿名请求。
  3. 而实际上/foo/hello需要非匿名认证。
  4. 访问决策投票器WebExpressionVoter做出了拒绝授权投票(Voted to deny authorization)。
  5. 在基于肯定(AffirmativeBased)的访问策略下本次请求授权失败,抛出AccessDeniedException异常。
  6. 异常响应过滤器ExceptionTranslationFilter对步骤⑤抛出的异常进行处理。
②访问拒绝处理

ExceptionTranslationFilter接收到AccessDeniedException异常后会交给handleAccessDeniedException方法处理,该方法的逻辑如图所示:
在这里插入图片描述
我们所涉及的逻辑只会有到步骤④,其逻辑为:
在这里插入图片描述
上面的逻辑会跳转到登录入口(如果有两个provider的话):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmnERpOg-1647437855521)(.\img\1644545563269.png)]

③发起OAuth2登录请求

我们点击gitee选项会向我们的后端服务器发起/oauth2/authorization/gitee请求:

GET /oauth2/authorization/gitee HTTP/1.1
Host: localhost:8082

对应的日志为:
在这里插入图片描述
从日志上看请求被OAuth2AuthorizationRequestRedirectFilter拦截,重定向到了Gitee授权服务器登录页面。

重定向的请求为:

GET /oauth/authorize?response_type=code&client_id=40f6a4018837&scope=user_info&state=j_y78k1M4A&redirect_uri=http://localhost:8082/login/oauth2/code/gitee HTTP/1.1
Host: gitee.com

涉及的参数有:response_typeclient_idscopestateredirect_uri,我们先不管这些参数是干嘛的,有个印象就好。

另外这个请求端点正好是配置中的authorization-uri配置项:

spring:
  security:
    oauth2:
      client:
        provider:
          gitee:
            authorization-uri: https://gitee.com/oauth/authorize      

OAuth2AuthorizationRequestRedirectFilter的作用就很清晰了:

  • 拦截/oauth2/authorization/{registrationId},这里registrationId=gitee
  • 组装registrationId对应providerauthorization-uri并发起重定向。

关于OAuth2AuthorizationRequestRedirectFilter的细节会在后面进行专门分析。

④用户授权

跳转到Gitee登录页面之后,后面的流程可以从浏览器记录中分析出来。
在这里插入图片描述

  • ① 点击login页面的gitee按钮,客户端服务器302重定向到授权服务器发起授权请求。
  • ② 授权服务器同意授权后,又302 重定向到了配置中的redirect_uri并附带一个codestate参数。
  • redirect_uri发起了请求。

安全起见,redirect_uri应当在授权服务器对应的客户端信息中注册,否则将被视为非法URI

redirect_uri请求我简化成HTTP脚本以方便加深印象:

GET /login/oauth2/code/gitee?code=a6e4cac6a7e&state=cR4FABTHbHj4ILZ HTTP/1.1
Host: localhost:8082
Referer: https://gitee.com/login

以下是授权服务器(gitee)302重定向/login/oauth2/code/gitee后的日志:
在这里插入图片描述
大致步骤为:

  1. redirect_uri请求被过滤器OAuth2LoginAuthenticationFilter拦截处理。
  2. 向gitee发出/oauth/token请求,该端点对应配置文件中的token-uri
  3. /oauth/token请求的响应被封装为OAuth2AccessTokenResponse对象实例。
  4. 向gitee发出/v5/user请求,该端点对应配置文件中的user-info-uri
  5. /v5/user请求的响应被封装为Map<String,Object>
  6. 根据某些策略对Session会话进行了处理(先了解即可)
  7. OAuth2AuthenticationToken存储到SecurityContextHolder中。
  8. 最后重定向到/foo/hello

须知

这个流程并不是标准的OAuth2流程,OAuth2中并不涉及用户登录认证,该登录认证是建立在信任Gitee用户的基础上做的认证,这一点要明白。

关于授权码的详细规范请参阅4.1 Authorization Code Grant,如果遇到疑难杂症,请联系我