Java 尝试运行jar文件时,清单主属性异常的签名文件摘要无效

Java 尝试运行jar文件时,清单主属性异常的签名文件摘要无效,java,intellij-idea,jar,Java,Intellij Idea,Jar,我正在尝试运行我的项目的jar文件。我正在研究intelliJ,并使用工件生成jar文件。但每次我试图运行我的jar文件时,它都会给我一个异常 java.lang.SecurityException: Invalid signature file digest for Manifest main attributes at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:284)

我正在尝试运行我的项目的jar文件。我正在研究intelliJ,并使用工件生成jar文件。但每次我试图运行我的jar文件时,它都会给我一个异常

java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
    at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:284)
    at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:238)
    at java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
    at java.util.jar.JarVerifier.update(JarVerifier.java:228)
    at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
    at java.util.jar.JarFile.getInputStream(JarFile.java:450)
    at sun.misc.JarIndex.getJarIndex(JarIndex.java:137)
    at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:839)
    at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:831)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.misc.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:830)
    at sun.misc.URLClassPath$JarLoader.<init>(URLClassPath.java:803)
    at sun.misc.URLClassPath$3.run(URLClassPath.java:530)
    at sun.misc.URLClassPath$3.run(URLClassPath.java:520)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.misc.URLClassPath.getLoader(URLClassPath.java:519)
    at sun.misc.URLClassPath.getLoader(URLClassPath.java:492)
    at sun.misc.URLClassPath.getNextLoader(URLClassPath.java:457)
    at sun.misc.URLClassPath.getResource(URLClassPath.java:211)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:365)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    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)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" 
然后将外部库添加到我的项目中

我做错了什么

更新

您的一些依赖项JAR是一个签名JAR,因此当您将所有JAR合并到一个JAR中并运行该JAR时,签名JAR的签名不匹配,因此您会遇到签名不匹配的安全异常

要解决这个问题,您需要首先确定哪些依赖项JAR都是已签名的JAR,然后排除它们。根据您使用的是MAVEN还是ANT,您必须采取适当的解决方案。下面是你可以阅读的更多内容

Maven:

<jar destfile="app.jar" basedir="${classes.dir}">
    <zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
    <manifest>
        <attribute name="Main-Class" value="app.Main"/>
    </manifest>
</jar>

org.apache.maven.plugins
maven依赖插件
2.6
解包依赖项
包裹
解包依赖项
系统
META-INF/*.SF
META-INF/*.DSA
META-INF/*.RSA
junit,org.mockito,org.hamcrest
${project.build.directory}/classes
ANT:

<jar destfile="app.jar" basedir="${classes.dir}">
    <zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
    <manifest>
        <attribute name="Main-Class" value="app.Main"/>
    </manifest>
</jar>


根据OP的评论更新:

<jar destfile="app.jar" basedir="${classes.dir}">
    <zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
    <manifest>
        <attribute name="Main-Class" value="app.Main"/>
    </manifest>
</jar>
“sqljdbc4.jar”是OP外部库中的签名jar。因此,遵循上述方法系统地排除与签名相关的文件,如.SF、.RSA或.DES或其他算法文件,是向前迈进的正确方法

如果未排除这些签名文件,则会因为签名不匹配而发生安全异常


如何知道JAR是否已签名?:如果JAR包含像.SF、.RSA或.DES这样的文件或其他算法文件,那么它就是已签名的JAR。或者运行
jarsigner-verify jarname.jar
并查看它是否输出“verifyed”

而不是删除META-INF文件,我更改了工件定义中的方法。我从工件中删除了“提取”库,并将其再次添加为“放入输出根”

通过这种方式,库将被合并,而不会对新的jar文件进行任何更改,我认为这是对库进行签名的目的


顺便说一下,我也在使用sqljdbc.jar。

在我的例子中,我通过maven shade插件使用uber jar,@ruhsuzbaykus answer就是解决方案。该策略似乎与@hagrawal的建议非常相似,但排除项是作为maven shade插件的过滤器配置添加的。

对于相同的问题,我已经完成了干净的安装并发布了。因此,清洁安装是一个选项,您可以使用新下载的jar进行构建。

只需从您的uber jar中筛选签名文件即可


org.apache.maven.plugins
maven阴影插件
3.2.4
包裹
阴凉处
真的
*:*
META-INF/*.SF
META-INF/*.DSA
META-INF/*.RSA

在编译的jar中,需要删除安全签名文件。要执行此操作,请执行以下命令


zip-d jarfile.jar'META-INF/.SF''META-INF/.RSA''META-INF/*SF'

我在我的
build.gradle.kts中添加了以下几行代码,它解决了这个问题

tasks.withType(){
排除(“META-INF/BC1024KE.RSA”、“META-INF/BC1024KE.SF”、“META-INF/BC1024KE.DSA”)
排除(“META-INF/BC2048KE.RSA”、“META-INF/BC2048KE.SF”、“META-INF/BC2048KE.DSA”)
}

在我的例子中,没有使用gradle或maven进行构建,我创建的工件是Jar类型


在构建工件之后,我得到的结果是一个jar文件。我将其重命名为.rar(或.zip)并将其作为存档文件打开,然后查找META-INF文件夹并删除所有扩展名为.SF、.DSA、.RSA的find,再次对其进行排序并重命名为.jar。完成。

你的罐子的内容是什么,你能打开罐子并发布其内容的屏幕截图吗?我已经更新了问题……检查一下@hagrawal@Fay007你好你找到解决办法了吗,我也有同样的问题,我搜索了很多,没有找到任何好的解决办法。谢谢虽然有点晚了,但我要评论一下:您的依赖项至少包括一个已签名的jar。您不应该像这里解释的那样提取依赖项:我在项目中没有看到任何类似的文件。这似乎是最有用的答案/建议。我正在使用Maven,但这并没有解决它,是否有任何新的解决方案@hagrawal?指定多个排除项的正确方法应该是在逗号分隔的列表中,如:“META-INF/*.SF,META-INF/*.DSA,META-INF/*.RSA”;否则,只有最后一个将被排除。依赖插件对我没有帮助,但过滤器也可以在shade插件中配置。这是使用Vert.x和SQL Server JDBC驱动程序时的最佳解决方案。我添加了一个关于这种情况的答案。此解决方案为我修复了SecurityException,但是
选项破坏了我的应用程序,因为它依赖于通过ServiceLoader机制加载其XML解析器的库(因此对解析器没有静态依赖)。启用
后,maven shade插件认为解析器是无法访问的代码,将其从jar中删除,我从ServiceLoader中得到了
java.util.ServiceConfigurationError
。从上面删除
会让我进入工作状态!如果使用,可以右键单击并按“打开存档”,查看内部文件,然后直接删除需要的文件。(比提取和重新压缩快得多)