springboot版本升級以及解決springsecurity漏洞的問題
背景
項目中要解決 Spring Security RegexRequestMatcher 認證繞過漏洞(CVE-2022-22978) 漏洞問題,并且需要將項目的版本整體升級到boot版本2.1.7,升級改造過程非常的痛苦,一方面對整個框架的代碼不是很熟悉,另外對解決漏洞問題相對較少。
需求
解決Spring Security RegexRequestMatcher 認證繞過漏洞(CVE-2022-22978) 漏洞,升級boot版本2.1.7
改造前父pom如下(部分依賴省略):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gisquest.realestate</groupId>
<artifactId>gisqrealestate-unityplatform-core</artifactId>
<version>2.2.1.RELEASE</version>
<modules>
<module>unityplatform-security</module>
<module>unityplatform-microauth</module>
<module>unityplatform-apigateway</module>
<module>unityplatform-servicediscovery</module>
<module>unityplatform-microappadmin</module>
<module>unityplatform-apigateway-core</module>
<module>unityplatform-apigateway-app</module>
<module>unityplatform-microauth-app</module>
<module>unityplatform-core-comm</module>
</modules>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot-admin.version>1.5.6</spring-boot-admin.version>
<jjwt.version>0.7.0</jjwt.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<swagger2.version>2.7.0</swagger2.version>
<apollo-client.version>1.0.0</apollo-client.version>
<jackson.version>2.10.2</jackson.version>
<!--micro version-->
<micro-apigateway.version>2.2.1.RELEASE</micro-apigateway.version>
<micro-auth.version>2.2.1.RELEASE</micro-auth.version>
<micro-comm.version>2.2.1.RELEASE</micro-comm.version>
<micro-apigateway.img.version>2.2.RELEASE</micro-apigateway.img.version>
<micro-auth.img.version>2.2.RELEASE</micro-auth.img.version>
<micro.img.version>2.2.RELEASE</micro.img.version>
<com.hanweb.SecurityUtil.version>1.0</com.hanweb.SecurityUtil.version>
<!--XStream -->
<xstream.version>1.4.20</xstream.version>
<spring.version>5.3.20</spring.version>
<spring-security.version>5.5.8</spring-security.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>漏洞解決方案
gisqrealestate-unityplatform-core 項目下 解決Spring Security RegexRequestMatcher 認證繞過漏洞(CVE-2022-22978) 漏洞
升級boot版本2.1.7(和快速構建保持一致)
注意下升級之后一些配置文件(例如redis,文件限制大小等) 和 代碼 不兼容問題
漏洞影響版本
5.5.0 <= Spring Security < 5.5.7
5.6.0 <= Spring Security < 5.6.4
版本改造問題
改造前 版本
<spring-cloud.version>Edgware.SR2</spring-cloud.version> <spring-boot.version>1.5.10.RELEASE </spring-boot.version>
升級到2.x版本
<spring-cloud.version>Greenwich.SR2</spring-cloud.version> <spring-boot.version>2.1.7.RELEASE</spring-boot.version>
問題一:項目改造前是自定義的springboot依賴,現要求去掉原先的自定義封裝依賴
剛開始我是把原先自定義的springboot依賴的父依賴直接移到最外層,大概過程如下,導致出現一堆問題。

坑一:類不存在,或包不存在
項目中出現大量的類不存在,但是明明可以用鼠標點擊進去,此類問題經常是idea,什么緩存,或者是pom依賴下載不全導致,然后就陷入了這個誤區(qū),一直以為是idea的問題。
先是清理 idea緩存、執(zhí)行mvn idea:idea命令等方式很多次還是無法解決。
然后分支代碼提交后,同事檢出也是同樣的問題,項目還是無法啟動,保錯也是提示類不存在等。
此時我就懷疑可能不是idea的問題了。
后面就換了一種方式
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> <relativePath /> </parent>
改成
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>改成這樣后終于正常了,不在提示類不存在,包不存在等問題了。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.gisquest.realestate</groupId>
<artifactId>gisqrealestate-unityplatform-core</artifactId>
<version>2.2.1.RELEASE</version>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>unityplatform-security</module>
<module>unityplatform-microauth</module>
<module>unityplatform-apigateway</module>
<module>unityplatform-servicediscovery</module>
<module>unityplatform-microappadmin</module>
<module>unityplatform-apigateway-core</module>
<module>unityplatform-apigateway-app</module>
<module>unityplatform-microauth-app</module>
<module>unityplatform-core-comm</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot-admin.version>1.5.6</spring-boot-admin.version>
<jjwt.version>0.7.0</jjwt.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<swagger2.version>2.7.0</swagger2.version>
<apollo-client.version>1.0.0</apollo-client.version>
<jackson.version>2.10.2</jackson.version>
<!--micro version-->
<micro-apigateway.version>2.2.1.RELEASE</micro-apigateway.version>
<micro-auth.version>2.2.1.RELEASE</micro-auth.version>
<micro-comm.version>2.2.1.RELEASE</micro-comm.version>
<micro-apigateway.img.version>2.2.RELEASE</micro-apigateway.img.version>
<micro-auth.img.version>2.2.RELEASE</micro-auth.img.version>
<micro.img.version>2.2.RELEASE</micro.img.version>
<com.hanweb.SecurityUtil.version>1.0</com.hanweb.SecurityUtil.version>
<!--XStream -->
<xstream.version>1.4.19</xstream.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
<eureka.version>2.1.0.RELEASE</eureka.version>
<openfeign.version>2.0.0.RELEASE</openfeign.version>
<zuul.version>2.1.2.RELEASE</zuul.version>
<commons-lang.version>2.6</commons-lang.version>
<commons-collections.version>3.2.2</commons-collections.version>
<commons-beanutils.version>1.9.3</commons-beanutils.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</project>坑二:idea中maven設置,最好調整成maven運行(推薦)
否則會出現稀奇古怪的問題,比如上面的之前用parent依賴方式我本地可以跑(奇了怪),但是同事拉下拉卻跑不了,切換成eclipse也同樣項目跑不起來。

經過一番折騰代碼是跑起來了總算不提示類不存等問題。
代碼兼容問題
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: org.springframework.security.core.authority.SimpleGrantedAuthority; local class incompatible: stream classdesc serialVersionUID = 420, local class serialVersionUID = 510
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:84) ~[spring-data-redis-2.1.10.RELEASE.jar!/:2.1.10.RELEASE]
解決方法:
redis跨版本升級后,需要把redis緩存清理一下
問題一:alibaba.fastjson.JSONObject cannot be cast to xx
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.gisquest.realestate.security.validate.code.ValidateCode
- 改造前邏輯
@Override
public ValidateCode get(ServletWebRequest request, ValidateCodeType validateCodeType) {
Object object = redisTemplate.opsForValue().get(buildKey(request, validateCodeType));
if (object == null) {
return null;
}
return (ValidateCode)object ;
}- 改造后
@Override
public ValidateCode get(ServletWebRequest request, ValidateCodeType validateCodeType) {
Object object = redisTemplate.opsForValue().get(buildKey(request, validateCodeType));
if (object == null) {
return null;
}
String josn =JSON.toJSONString(object);
return JSONObject.parseObject(josn,ValidateCode.class);
}問題解決?。。。?/p>
問題二:升級后通過feign調用認證服務接口/oauth/check_token接口提示如下
Illegal hexadecimal character - at index 8
org.apache.commons.codec.DecoderException: Illegal hexadecimal character - at index 8
at org.apache.commons.codec.binary.Hex.toDigit(Hex.java:286)
at org.apache.commons.codec.binary.Hex.decodeHex(Hex.java:106)
at com.gisquest.realestate.utils.Encodes.decodeHex(Encodes.java:41)
原因版本問題
改造前spring-security-core-4.2.4.RELEASE
在AbstractUserDetailsAuthenticationProvider在實現類中additionalAuthenticationChecks方法邏輯如下
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
Object salt = null;
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
}- 改造后
spring-security-core-5.1.6.RELEASE版本中AbstractUserDetailsAuthenticationProvider在實現類中改方法additionalAuthenticationChecks
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) {
this.logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
} else {
String presentedPassword = authentication.getCredentials().toString();
if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
this.logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
}邏輯變化了

使用了自定義的密碼加密類

密碼加密方式發(fā)現不一樣了,因此按照原先代碼邏輯獲取到的前后密碼其實是一樣的,但是升級后GisqPasswordEncoder起了作用,因此在比較時應該時加密后的匹配

因此改成這樣

問題三:feign調用token校驗接口,在項目中未搜索到
后來打斷點才發(fā)現竟然后spring-security-oaruth2包內部類CheckTokenEndpoint中的接口,無語,我還以為是自己定義的呢找了半天未找打?。。。?!
jar包依賴沖突問題
方式一:選擇依賴的模塊,鼠標右鍵,選擇show dependency
如果有沖突會出現報紅?。?!

方式二:安裝一個maven-helper插件
如果有沖突會自動顯示,然后去排處即可

總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java實現并發(fā)執(zhí)行定時任務并手動控制開始結束
這篇文章主要介紹了Java實現并發(fā)執(zhí)行定時任務并手動控制開始結束,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
Spring Boot集成Shiro實現動態(tài)加載權限的完整步驟
這篇文章主要給大家介紹了關于Spring Boot集成Shiro實現動態(tài)加載權限的完整步驟,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09
基于SpringBoot和Vue實現分片上傳系統(tǒng)
最近想做一個關于文件上傳的個人小網盤,一開始嘗試使用了OSS的方案,但是該方案對于大文件來說并不友好,所以開始嘗試分片上傳方案的探索,接下來小編給大家詳細的介紹一下如何基于SpringBoot和Vue實現分片上傳系統(tǒng),需要的朋友可以參考下2023-12-12

