JKS (Java KeyStore) 是一种存储加密密钥、证书和其他安全证书的容器格式。JKS 文件通常通过 keytool 工具来创建和管理。
一、报错
java.lang.RuntimeException: java.io.IOException: Invalid keystore format
Caused by: java.io.IOException: Invalid keystore format
二、原因
可能原因:1、Java的密钥库jks文件放在/src/main/resources目录下,编译后jks文件被修改,导致keyStore.load读取keystore文件异常
2、生成的JKS有问题
结论:我的是因为原因1导致的
导致报错的pom.xml配置:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<resource>
filtering:表示是否启用资源文件的过滤功能
设置true可以替换文件中的 ${…} 占位符为具体的值(java开发在pom.xml配置多环境使用到);设置false,则禁止对这些文件进行过滤处理。
多环境配置需要替换文件中的占位符(如 ${server.port})为具体的值。这对于配置文件是非常有用的,但对于二进制文件(如 oauth2.jks)会导致格式错误。
对于 oauth2.jks 特殊二进制文件,应该禁用 Maven 的资源过滤功能,以免在构建过程中修改文件内容,导致格式错误。
二、分析(验证是否是maven配置过滤功能问题)
1、springboot项目,配置pom.xml
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</build>
2、创建 JKS 文件示例
- 生成自签名证书并将其放入一个新的 JKS 文件:
keytool -genkeypair -alias myalias -keyalg RSA -keystore oauth2.jks
-storepass 123456 -validity 365
这个命令将会生成一个包含自签名证书的 JKS 文件,文件名为 oauth2.jks,存储密码为 123456。
全部填写一样也是可以的,比如全部填写oauth,然后确认信息输入: 是
最后直接回车,密码也是保持123456
- 检查 JKS 文件的内容:
keytool -list -v -keystore oauth2024.jks -storepass 123456
这个命令将显示 JKS 文件的详细信息。
示例代码读取 JKS 文件
确保你的 JKS 文件格式正确后,使用以下代码读取 JKS 文件:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import org.springframework.core.io.ClassPathResource;
public class KeyStoreExample {
public static void main(String[] args) {
getKeyStore1();
}
// 读取成功
public static void getKeyStore1() {
String keyStorePath = "D:\\20240603\\oauth2.jks";
char[] keyStorePassword = "123456".toCharArray();
try (FileInputStream fis = new FileInputStream(keyStorePath)) {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(fis, keyStorePassword);
System.out.println("KeyStore1 has been successfully loaded.");
} catch (Exception e) {
e.printStackTrace();
}
}
// 读取失败,格式错误
public static void getKeyStore2() {
try {
KeyStore keyStore = KeyStore.getInstance("JKS");
// 确保 oauth2.jks 文件在 resources目录下
InputStream inputStream = new ClassPathResource("oauth2024.jks").getInputStream();
keyStore.load(inputStream, "123456".toCharArray());
System.out.println("KeyStore has been successfully loaded.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意事项:1. 路径正确性 2. 密码正确性
比对编译前后的jks文件大小是否一致,发现不一致。就是编译之后被修改了,读取了会报格式异常。
除非读的不是编译之后的,直接使用全路径读取本地文件 或者 不放在resources目录下
三、解决方法
3.1 解决方法一:JKS特殊二进制文件不放在resource目录下
3.2 解决方法二:使用绝对路径访问文件(全路径,如D:\oauth2.jks)
使用绝对路径访问oauth2.jks 是可以的,使用相对路径访问到是编译之后的文件
3.3 解决方法三:仅对oauth2.jks 文件不设置资源过滤,兼容多环境设置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<!--第一个 resource 禁用了过滤功能,适用于 oauth2.jks 这类二进制文件-->
<filtering>true</filtering>
<excludes>
<exclude>oauth2.jks</exclude>
</excludes>
</resource>
<!--第二个 resource 启用了过滤功能,并排除了 oauth2.jks,确保其他配置文件能够正常替换占位符-->
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>oauth2.jks</include>
</includes>
</resource>
</resources>
</build>
maven clean一下,选中pom.xml 重新加载
或者rebulid都行
再次运行就能正常访问了