华企号 互联网综合 SpringSecurity OAuth实现单点登录源码解析-彻彻底底

SpringSecurity OAuth实现单点登录源码解析-彻彻底底

前言
这篇文章是建立在对SpringSecurity、SpringSecurity OAuth 、OAuth2.0协议、SSO单点登录流程有所了解的基础上,如果这部分不了解的话,源码分析起来就会比较处理,这个流程都稀里糊涂的,这篇文章会从一个未登录授权的请求,从SpringBoot集成的Tomcat一步一步到SpringSecurity再到SpringSecurity OAuth整个授权过程和单点登录的源码流程分析

环境准备
一个完整流程的SSO单点登录项目!​ ​完整项目地址​​

项目clone下来后项目结构如下

 

 

这里建议不要直接使用IDEA打开security文件,推荐将sso-demo打成本地依赖,然后单独将sso-client1、sso-client2、sso-server使用IDEA打开,方便后面源码调试,因为在同一个IDEA中打开设置的断点,三个项目公用的依赖中的代码会重复的执行,跳来跳去,不便于我们调试!

源码分析
这里先发送一个请求,http://127.0.0.1:9992/client1/index.html,然后一路跟着下面断点走

 

 

注意:这是NetWork中什么都没有,这个没登录授权的请求,会被下面断点一个一个卡住!1.标记CoyoteAdapter-service

—————————————————————–Tomcat接管请求—————————————————————

 

 

这是整个请求到达Tomcat的入口,可以理解为请求的大门!

2.标记invoke()方法

 

 

后续还有很多的invoke()方法需要标记,都是底层Tomcat的调用关系实现!

3.标记StandardEngineValve类中invoke()方法

 

 

4.标记ErrorReportValve类中invoke()方法

 

 

5.标记StandardHostValve类中invoke()方法

 

6.标记AuthenticatorBase类中invoke()方法

 

 

7.标记StandardContextValve类中invoke()方法

 

 

8.标记StandardWrapperValve类中invoke()方法

 

 

 

 

注意断点走到这里后得到filterChain为ApplicationFilterChain对象,然后调用ApplicationFilterChain类中的doFilter()方法

9.标记ApplicationFilterChain类中internalDoFilter()方法

 

 

 

 

doFilter()方法中的两个断点就可以不用打了,因为会循环调用internalDoFilter()方法

 

 

最后选择org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean中的doFilter()方法,这里走到DelegatingFilterProxy类中SpringWeb开始开始接管代码流程

———————————————————–SpringWeb接管请求—————————————————————-

 

10.标记DelegatingFilterProxy类中doFilter()方法

 

 

这里会调用本类中的invokeDelegate()方法,顺带标记一下

 

 

得到此时delegate值为FilterChainProxy11.标记FilterChainProxy类中doFilter()方法

进入这里是SpringSecurity已经开始接管请求

———————————————————SpringSecurity接管请求————————————————————

 

此处调用本类中的doFilterInternal()方法,

 

 

在doFilterInternal()方法中又会调用doFilter()方法,注意!!!此处的doFilter()方法不是刚开始的那个doFilter()方法而是下面的

 

 

这里又会进入循环

 

 

一直会等待值为FilterSecurityInterceptor,这是因为引入了SpringSecurity后才有的,那么这里就可以理解为请求开始正式进入SpringSecurity管控了,已经从Tomcat中脱离出来,开始走SpringSecurity的流程,在之前的文章中也有写过这个FilterSecurityInterceptor拦截器,这个拦截器我们可以理解为是SpringSecurity的大门!12.标记FilterSecurityInterceptor的doFilter()方法

 

 

这里会调用本类的invoke()方法

标记invoke()方法

 

 

进入beforeInvocation()方法13.标记AbstractSecurityInterceptor类中beforeInvocation()方法

 

 

这行代码比较重要

this.accessDecisionManager.decide(authenticated, object, attributes);
1.
在SpringSecurity起到一个决定作用,关系到请求的通过情况!
当然了这里刚开始发送的http://127.0.0.1:9992/client1/index.html这个请求是没有登录授权的,那么在行代码就会报错

14.标记AffirmativeBased类中decide()方法

 

 

这里就会抛出异常然后又会被AbstractSecurityInterceptor类中beforeInvocation()方法decide调用处捕获异常,代码如下

 

 

然后这里的异常又会抛出

被ExceptionTranslationFilter接收这个类在写SpringSecurity有提到过,是一个SpringSecurity过滤器连上重要的一环

 

 

中间蓝色的就是这个异常过滤器!最终会原路返回到CoyoteAdapter中

 

 

这里会向浏览器中发送重定向login地址

 

 

作者: 华企网通李铁牛程序员

我是程序员李铁牛,热爱互联网软件开发和设计,专注于大数据、数据分析、数据库、php、java、python、scala、k8s、docker等知识总结。15889726201 我的座右铭:"业精于勤荒于嬉,行成于思毁于随"
上一篇
下一篇

发表回复

联系我们

联系我们

028-84868647

在线咨询: QQ交谈

邮箱: tech@68v8.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部