首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何

编程知识
2024年07月29日 07:45

开心一刻

今天上午,同事群中的刘总私聊我
刘总:你来公司多久了
我:一年了,刘总
刘总:你还年轻,机会还很多,年底了,公司要裁员
刘总语重心长的继续说到:以后我们常联系,无论以后你遇到什么困难,找我,我会尽量帮你!
我:所以了,我是被裁了吗,呵,我爸知道吗?
刘总:知道,今天上午保安部已经出名单了,你爸也在里面
我:我妈知道吗?
刘总:保洁也裁
我:刘总,你做这些事情问过我爷爷吗?
刘总:门卫也裁
我心里咯噔一下,这它妈哒团灭了呀

团灭

安全漏洞

公司的测试部门会定期扫描代码,检测出安全漏洞,导出 Excel放到群里,各个项目的负责人针对性去修复(升级组件版本),因为某些原因不能修复的,需要给出原因(有些组件版本依赖更高的 JDK 版本,而 JDK 又不能升)。而我负责的项目是基于 Spring Boot 2.7.18,它依赖的 logback 版本是 1.2.12,存在安全漏洞 CVE-2023-6378

CVE-2023-6378

我本意是非常拒绝修这玩意的,修的时候得评估影响点,测的时候需要都覆盖到;核心组件的升级不亚于一次重构,开发和测试都得全量测。重点是,修好不算产出,修坏了可是要背锅的,我可是经历过血的教训的:都说了能不动就别动,非要去调整,出生产事故了吧,总之还是那句话

能不动就不要动,改好没绩效,改出问题要背锅,吃力不讨好,又不是不能跑

纵使我有万般的不愿,但也不得不修,公司对安全漏洞这一块非常重视,毕竟要给客户留下非常专业的形象。既然避无可避,那就坦然接受,充分评估影响点,做好全面的测试

干就完了

漏洞修复

如何修复,想必大家都知道,剔除掉 spring-boot-starter-logging 依赖,引入新版本依赖,如下所示

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>${logback.version}</version>
</dependency>

升级到哪个版本,就值得仔细斟酌一番了。反正都要升级,那何不升级到最新版?安全漏洞少,甚至暂时没漏洞。那也不是,因为 logback 依赖 JDK 版本,官方说明如下

logback与jdk关系

因为项目依赖的 JDK 版本是 8,所以我们将 logback 升级到 1.3 的最新版是最合适的;logback 1.3.x 依赖的 SLF4J 版本是 2.0.x,所以最终 pom.xml 调整成如下

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <logback.version>1.3.14</logback.version>
    <slf4j.version>2.0.7</slf4j.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>spring-boot-starter-logging</artifactId>
                <groupId>org.springframework.boot</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
</dependencies>
logback1.3.14

貌似挺简单的,对吧?编译也不报错,一切都很顺利;一旦你运行,最烦人的 bug 就来了

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:304)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:118)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:220)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
	at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:79)
	at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:56)
	at java.util.ArrayList.forEach(ArrayList.java:1249)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
	at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:56)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:299)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
	at com.qsl.Application.main(Application.java:15)
Caused by: java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 17 more

此时,你们会怎么办?本着快速解决 bug 的原则,我们也只能上网查问题

java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder

看能不能找到解决办法;可一通查下来,各种尝试,该问题都得不到解决,除非将 logback 版本降到 1.2.x,可最新的 1.2.13 是有不少安全漏洞的

logback1.2.13漏洞

那没别的办法了,只能去追查问题产生的原因了,找到原因就好对症下药了。问题又来了,如何去查原因了,最直接、最有效的办法就是从异常堆栈信息入手

异常堆栈

鼠标左击 LogbackLoggingSystem.java:304,然后就来到 spring-boot-2.7.18 的源码

LogbackLoggingSystem_304

这里用到了 StaticLoggerBinder,在往上滑到 LogbackLoggingSystemimport 部分,StaticLoggerBinder 的全类路径是

org.slf4j.impl.StaticLoggerBinder

logback 1.2.12 是有这个类的

logback1.2.12_StaticLoggerBinder

logback 1.3.14 不仅没有该类,连 org 包都不存在了

logback1.3.14_StaticLoggerBinder不存在

所以,原因是不是找到了?

spring-boot-2.7.18 依赖 org.slf4j.impl.StaticLoggerBinder,而 logback 1.3.14 没有该类

那如何对症下药了?不仅你们懵,我也懵

懵

调整下思路,这个问题我们肯定不是第一个遇到的,对吧,肯定有人在 spring-boot 的官方提问,我们去搜搜 org/slf4j/impl/StaticLoggerBinder

springboot2.7.x不支持logback1.3.x

点进去,里面有官方人员给出的答复,我给大家翻译一下;提问者是 LSmyrnaios,他做了一下背景介绍

logback 1.3.x 基于 Java 8,1.4.x 基于 Java-11,而 Spring Boot 只在 3.x.x 中集成了 logback 1.4.x(基于 Java-11)

Java-8 用户被遗忘了

根据 logback 文档说明,logback 同时维护 1.3.x 和 1.4.x,也就是说,logback 1.3.x 是 '活跃的',Spring Boot 2.7.x 应该集成它

请考虑以下案例:

我有一个Java-8应用程序,使用 logback v.1.3.6,运行没问题

现在,我想将该应用程序集成到 Spring Boot v.2.7.9,运行的时候胞如下错误:

(异常堆栈跟我们遇到的一样,不展示了)

看起来像是 Spring Boot 用的 slf4j 1.7.x,但是 logback 1.3.x 用的 slf4j 2.0.x,所以 StaticLoggerBinder 类不见了

所以,你们能够在 Spring Boot >= 2.7.x and < 3 的版本中支持 logback 1.3.x 吗

先谢谢了.

这么看来,这哥们遇到的问题跟我们的一样,提出的诉求也跟我们一样,是不是看到了希望?

官方人员 scottfrederick 给出了回复

scottfrederick回复

翻译过来就是

LSmyrnaios 感谢你的联系。 Spring Boot 2.7.x 依赖 Logback 1.2.x。 已经在第三方升级政策中说明过了,我们不会在 2.7.x 的版本中升级 Logback到 1.3.x。正如你提到的,我们不仅仅要升级 Logback 到 1.3.x,还需要将 SLF4J 升级到 2.0.x,这有一个关于我们为什么不在 2.7.x 升级的讨论,所以我们做补丁发布

第三方依赖升级说明如下

Third-party dependencies

简单点来说就是:第三方依赖的补丁级别的修复,可以在 Spring Boot 的补丁版本中升级,而第三方依赖的次要或者主要版本的升级,则只能在 Spring Boot 的次要或主要版本中升级。不能在 Spring Boot 的补丁版本中升级第三方依赖的次要或者主要版本。这里的补丁版本可以理解成小版本,也就是 1.2.x 中的 x,而次要或者重要版本,则是 1.x.x 中的第一个 x,也就是我们所说的大版本

关于 scottfrederick,他可不是 Spring Boot 的普通 Contributor,人家可是榜六大哥

榜六

他说的还是很有权威的;关于他提到的讨论,我们后面在看,先把当前的看完。提问者 LSmyrnaios 又说了

LSmyrnaios 补充

翻译过来就是

scottfrederick,我们接着刚刚的讨论,我想问的是,是否有可能在 Spring Boot 的下一个大版本(比如 2.8.0,如果在计划中的话)将 SLF4J 升级到 2.0.x,logback 升级到 1.3.x

这对于大量的 Java 8 用户来说非常重要,他们希望为生产系统提供最新的安全和错误修复

先谢谢了

scottfrederick 说的就很符合我们的期望,我们接着往下看。wilkinsona 给出了回复

wilkinsona回复

翻译过来就是

目前没有 Spring Boot 2.8 的计划

言简意赅,弦外之音就是 Spring Boot 2.x.x 就是不支持 Logback 1.3.x,满满的任性感。你们是不是很好奇这任性的哥们是谁?人家可是 Spring Boot 的榜一大哥!!!

榜一大哥

是不是觉得他任性的理所当然了?我们继续往下看,ASarco 说了一句

ASarco

翻译过来就是

现在的问题是 logback 1.2.12 存在安全漏洞 cve-2023-6378,对于 2.7.x 的煞笔用户却没有一个结论

这哥们表达了自己得愤懑,都直接飙国粹(SB)了,那是相当的气愤呀

SB 是 Spring Boot 的简写,并非国粹,大家别被误导了!!!

针对 ASarco 的问题,后面有人给了回复,可以升级 Logback1.2.13 来修复漏洞 cve-2023-6378,而我们也没得选了,只能将 Logback1.3.14 降到 1.2.13,最终的 pom.xml 如下所示

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<logback.version>1.2.13</logback.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>spring-boot-starter-logging</artifactId>
                <groupId>org.springframework.boot</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>
</dependencies>

所以,1.2.13 的安全漏洞仍是存在的,下次扫描出来后我们直接说明如下

修复不了,Spring Boot 2.7.x 官方不打算支持 Logback 1.3.x,除非升级 Spring Boot 到 3.x.x(集成的是 Logback 1.4.x),但同时需要将 JDK 升级到 11

讨论

还记得前面提到的那个讨论吗,因为比较长,我挑一些重点给大家翻译下

1、wilkinsona 提到了 Logback 的一次 commit,这次提交移除了 StaticLoggerBinder

StaticLoggerBinder移除记录

1.3.0-alpha0 版本就移除了 StaticLoggerBinder,所以 Spring Boot 2.7.x 不能集成 Logback 1.3.x 的任何一个版本

2、snicoll (榜二大哥) 提到了一个很重要的点

snicoll_讨论

Spring BootLoggingSystem 是可以禁用或者改变的

-Dorg.springframework.boot.logging.LoggingSystem=none

3、wilkinsona 提到了 spring.factories 中的 ApplicationListener,其优先级高于 org.springframework.boot.context.logging.LoggingApplicationListener,可以用来设置系统属性以响应 ApplicationStartingEvent

4、wilkinsona 针对 cmuchinsky 提出的

对于 spring boot 2.7,是否有可能更新 ogbackLoggingSystemlogback 来兼容 Logback 1.3 与 1.2,例如反射

给出了回答,他认为这不太可能,支持 Logback 1.4 所需的更改范围太广,无法通过反射并行支持 1.2 和 1.3/1.4

5、zhaolj214 通过读源代码,找到了一种解决方案

@SpringBootApplication
public class Spring5Application {
    public static void main(String[] args) {
        System.setProperty("org.springframework.boot.logging.LoggingSystem", "none");
        SpringApplication.run(Spring5Application.class, args);
    }
}

至于正确与否,我们下篇再试

6、wilkinsona 说明了可以自定义日志:howto.logging

总结下来就是:针对 Spring Boot 2.7.x,官方不会支持 Logback 1.3.x,但还是可以通过自定义的方式去支持 Logback 1.3.x,具体如何自定义,以及效果如何,且听下回分解

总结

  1. Logback 1.3 依赖 JDK 8,1.4 依赖 JDK 11;Spring Boot 2.7.x 依赖 Logback 1.2.x,而 3.x.x 依赖 Logback 1.4.x。也就说 Spring Boot 跳过了 Logback 1.3.x
  2. Spring Boot 官方也给出了答复,根据第三方依赖政策(小版本升级小版本,大版本升级大版本),2.7.x 不会支持 Logback 1.3.x,而 3.x.x 索性直接支持 Logback 1.4.x
  3. 非要 Spring Boot 2.7.x 支持 Logback 1.3.x 也不是不可以,需要调整配置,还存在一些限制,具体细节请看下篇
From:https://www.cnblogs.com/youzhibing/p/18327929
本文地址: http://shuzixingkong.net/article/534
0评论
提交 加载更多评论
其他文章 (2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办?
OpenAI升级ChatGPT plus时可能会遇到升级报错【您的银行卡被拒绝了/your card has been declined」,教你快速解决并升级成功
(2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办? (2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办?
LeetCode654. 最大二叉树
题目链接:https://leetcode.cn/problems/maximum-binary-tree/description/ 题目叙述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。 递归地在最大
LeetCode654. 最大二叉树 LeetCode654. 最大二叉树
C语言中的断言函数assert
简介 assert 是 C 语言中的一个宏,用于在程序运行时进行条件检查,主要用于调试目的。它在 &lt;assert.h&gt; 头文件中定义,用于验证程序中的假设条件是否成立,如果不成立,程序将打印错误信息并终止执行。 特点 调试用途:主要用于捕获程序中的逻辑错误或不期望的条件。 可移除:通过定
萌新的装机体验(持续更新)
萌新的装机体验 起因 作为一名 OIer,平日划水的方式无非就是看看 edge 首页和知乎(当然如果教练不在就上 B 站了)。有一天在 edge 主页上忽然看到了一个 5000 元主机的装机体验,看完之后就想换台电脑了。 家里的那台电脑是我小学毕业的时候和我爸自己装的。当时什么都不懂(但以为自己很懂
《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇
1.简介 前边的两篇文章中,宏哥分别对input控件上传文件和非input控件上传文件进行了从理论到实践地讲解和介绍,但是后来又有人提出疑问,前边讲解和介绍的都是上传一个文件,如果上传多个文件,Playwright是如何实现的呢?宏哥看了一下官方的API也有上传多个文件的API,那么今天就来讲解和介
《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇 《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇 《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇
这才是 PHP 高性能框架 Workerman 的立命之本
在这个大家都崇尚高性能的时代,程序员的谈笑间句句都离不开高性能,仿佛嘴角边不挂着「高性能」三个字都会显得自己很 Low,其中众所皆知的 Nginx 就是高性能的代表。
这才是 PHP 高性能框架 Workerman 的立命之本
70%的人都答错了的面试题,vue3的ref是如何实现响应式的?
最近在我的vue源码交流群有位面试官分享了一道他的面试题:vue3的ref是如何实现响应式的?下面有不少小伙伴回答的是Proxy,其实这些小伙伴只回答对了一半。
70%的人都答错了的面试题,vue3的ref是如何实现响应式的? 70%的人都答错了的面试题,vue3的ref是如何实现响应式的? 70%的人都答错了的面试题,vue3的ref是如何实现响应式的?
一键语法错误增强工具 ChineseErrorCorrector
一键语法错误增强工具 欢迎使用我最近开源的使用一键语法错误增强工具,该工具可以进行14种语法错误的增强,不同行业可以根据自己的数据进行错误替换,来训练自己的语法和拼写模型,希望推动行业文本纠错的发展,欢迎Star,14种错误如下所示: 每种错误类型,对应的使用方法,如下所示: 环境的安装 pip i
一键语法错误增强工具 ChineseErrorCorrector