• 如何全面升级spring-boot-2.x及Spring-security-oauth2


    背景介绍

    老的项目基于spring-boot-1.5.x、spring-security-oauth2-2.x实现的sso,在近期的安全漏洞扫描中发现如下2个漏洞:

    漏洞

    涉及jar

    修复方案

    Spring Framework JDK >= 9 远程代码执行漏洞(CVE-2022-22965)

    spring-core-4.3.12.RELEASE.jar

    升级官方安全版本 >= 5.3.18/5.2.20

    Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978)

    spring-security-core-4.2.3.RELEASE.jar

    5.5.x 版本使用者建议升级至5.5.7及其以上;
    5.6.x 版本使用者建议升级至5.6.4及其以上

    然后笔者的同事将spring-boot升级到了2.5.14;将spring-security-oauth2升级到了2.1.0、RELEASE,这样一来,spring-core的版本被间接的升级到了5.3.20,spring-security-core版本变成了5.5.8(主要是spring-boot决定的)。

    因为spring-boot-1.x和2.x之间的差距,同步的对项目依赖和代码做了微调。这里不再列出。不是今天的重点。

    项目终于能成功启动了,但是一个致命的问题出来了,登录成功后,不能正确的回跳到redirect_uri指定的地址。这里如果你对spring-security-oauth2实现登录认证不熟悉的,可以参考使用Spring Security搭建一套OAuth 2.0架构

    先说一下升级前是正常的。

    正常的登录流程

    1、浏览器输入http://localhost:8091/sso/oauth/authorize?redirect_uri=http://www.baidu.com&client_id=auth&response_type=code&scope=all然后回车
    2、系统检测到当前浏览器没有登录,跳转到登录界面
    在这里插入图片描述

    3、输入用户名和密码,后点击登录,跳转到第一步redirect_uri指定的地址,并且地址栏带回code
    在这里插入图片描述

    升级后第3部会出现继续跳转登录的问题,而且跳转失败

    在这里插入图片描述
    F12看到刚才点击登录的时候,请求了http://localhost:8091/sso/api/v1/login

    在这里插入图片描述
    这一步是没有问题的,但是为啥UsernamePasswordAuthenticationFilter拦截器没有拦截,然后进行用户名和密码的校验呢?而是当成了一次普通没认证的请求,再次跳转http://localhost:8091/sso/index.html。

    这里开始上笔者的代码

    在这里插入图片描述

    分析:

    1、当第1步请求gethttp://localhost:8091/sso/oauth/authorize的时候是需要认证的,所以跳转到loginPage对应urlhttp://localhost:8091/sso/api/v1/login。这里sso/api/v1/login是笔者自定义的接口,接着又redirect到sso/index.html对应的登录界面。截止到这里都是没有问题的。

    2、点用户点击登录按钮的时候,请求了posthttp://localhost:8091/sso/api/v1/login进行密码校验。此时应该被UsernamePasswordAuthenticationFilter拦截到,然后执行下面的密码校验才对:
    在这里插入图片描述
    为什么没有拦截到呢?

    跟源码

    我们从FilterChainProxy类开始看,因为该类回给每一个请求组装一个List,然后执行依次执行这个FilterChain中的每个xxxFilter。
    在这里插入图片描述
    debug看一下filterChains究竟有哪些匹配规则:
    在这里插入图片描述
    首先,0、1、2、3的pattern都不能匹配到posthttp://localhost:8091/sso/api/v1/login排除。
    剩下4、5是我们重点关注对象,到底是谁匹配了/sso/api/v1/login这个前缀,然后里面filter还不包括UsernamePasswordAuthenticationFilter ?
    在这里插入图片描述
    继续跟进4的NotOauthRequestMatcher:
    在这里插入图片描述
    这里是个逆向思维,如果请求的前缀不在下面范围内,认为匹配改fliterChain
    0 = “/oauth/confirm_access”
    1 = “/oauth/check_token”
    2 = “/oauth/error”
    3 = “/oauth/token”
    4 = “/oauth/authorize”
    那问题明了了,我们的/sso/api/v1/login刚好不在这个范围内,所以就使用了下面这些filter
    在这里插入图片描述
    刚好没有真正需要的UsernamePasswordAuthenticationFilter。一顿操作发现还没认证,就重新跳转到登录界面了。

    结论

    因为升级之后,spring-security-web中匹配规则发生了变化,导致没有点击登录按钮时请求的posthttp://localhost:8091/sso/api/v1/login没有被UsernamePasswordAuthenticationFilter拦截到,登录失败了。

    反证结论是否正确

    说明是升级导致的问题,那我们回退代码,跟进老版本FilterChainProxy中的的逻辑看看:
    在这里插入图片描述
    的确如此,老版本中,自定义的匹配4规则在NotOauthRequestMatcher 6之前,所以不存在截胡的现象。

    解决方案

    既然问题是fliterChain的顺序导致的,那有没有可能调整FilterChainProxy#filterChains来解决呢?经常源码跟踪发现这里似乎没有给开发者留“口子”。

    换个思路,既然是xxxx#NotOAuthRequestMatcher这个fliterChain截胡了,那能否想办法让这个RequestMatchar#match匹配失败呢?
    在这里插入图片描述
    修改paths的元素,将我们自定义的请求/sso/api/v1/login加入进去。
    在这里插入图片描述
    通过测试,问题得到解决。

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    工作好多年,回忆人生--高中三年
    【STM32 CubeMX】移植u8g2(一次成功)
    防火墙介绍
    【机器学习】聚类算法中的 K-means 算法及其原理
    vue3,axios获取的数据渲染不到页面上
    Java项目:JSP员工出差请假考勤管理系统
    SpringBoot对接OpenAI
    阿里云CDN缓存配置及优化-oss绑定CDN缓存自动刷新功能
    微信小程序 request合法域名 中设置WebSocket的wss/ws报错 该域名协议头非法 问题解决
    电脑键盘功能基础知识汇总
  • 原文地址:https://blog.csdn.net/egegerhn/article/details/126081102