今天,我们的重点工作是对monorepo
系统的文件导入做安全控制,主要是通过判断文件的扩展名和类型,来限定用户导入文件的合法性,防止非法文件进入系统造成风险。
我们借用了此前在另一个系统zfquan
基于Apache Tika
的解决方案。
不巧,在运行main程序时,出现了一个 NoClassDefFoundError
错误-未找到Apache Commons IO
(commons-io)类库的一个class的定义。
20:25:14.667 [main] DEBUG org.apache.tika.config.TikaConfig - loading tika config from defaults; no config file specified
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/input/UnsynchronizedByteArrayInputStream
at org.apache.tika.config.TikaConfig.getDefaultMimeTypes(TikaConfig.java:317)
at org.apache.tika.config.TikaConfig.<init>(TikaConfig.java:246)
at org.apache.tika.config.TikaConfig.getDefaultConfig(TikaConfig.java:390)
at org.apache.tika.Tika.<init>(Tika.java:119)
at com.emax.zhenghe.common.util.TikaFileSecurityUtils.<init>(TikaFileSecurityUtils.java:20)
at com.emaxcard.car.TestMain.main(TestMain.java:38)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.input.UnsynchronizedByteArrayInputStream
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 6 more
Process finished with exit code 1
NoClassDefFoundError(而不是 ClassNotFoundException) 表示编译时类存在,但运行时找不到。
常见原因:
-
依赖未正确引入。
-
依赖冲突导致类加载失败。
-
打包时遗漏了 commons-io.jar(如 maven-shade-plugin 未正确包含依赖)。
同样的Tika,为什么搬到monorepo
就不行了呢?
经查maven依赖,monorepo
系统与zfquan
系统所依赖的 commons-io 的版本不同,zfquan
是2.16.1,monorepo
是2.6,这导致了问题的发生。
与单体结构的zfquan
所不同的是,monorepo
是一个庞大的同时拥有基础lib库和上层应用的工程。我们是在lib库的 sby-component-dfs 包 中添加的Tika依赖。
我尝试在其中一个应用层pom里显式添加 commons-io:2.16.1
,是可以解决问题的。
但,monorepo
有多达数十个应用,我显然不能在这么多应用层里显式添加 commons-io:2.16.1
依赖。而且,这不符合我们的系统开发规范————maven包依赖统一在顶层pom来管理。
那么,如何继续解决呢?
通过应用的maven依赖树(dependency:tree)得知,commons-io:commons-io:jar:2.6
是直接作为顶层依赖引入的(没有被其他库传递依赖)
然后我在IDE中全局查找 <artifactId>commons-io</artifactId>
,发现在顶层maven依赖管理文件 spring-base.pom 中,的确显式定义了 commons-io 的版本号!
<properties>
...
<commons.version>2.6</commons.version>
</properties>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
如此,我把这个版本号变更为 2.16.1 ,也是可以解决问题的。
但,monorepo
项目庞大,这样可能会拆东墙补西墙————可能影响其他用到commons-io的系统功能。
so,我们得针对 Tika 版本来做文章,找到适配 commons-io:2.6
的版本。
DeepSeek很快给出答案:Tika 2.4.1依赖commons-io:2.6
。开发者将 Tika 版本从 2.9.1 降级到 2.4.1,不再出现NoClassDefFoundError
错误,并且经测试,这个版本的Tika可以满足我们对系统文件导入的安全控制。