我有一个代码,该代码调用受证书保护的rest api,并且该代码运行了一段时间没有出现问题,直到我将应用程序从Wildfly 10迁移到Wildfly16。
代码本身很简单,它创建http请求并设置自定义套接字工厂:`
private SSLSocketFactory getSSLSocketFactory() {
char[] certPassword = {}; // password hidden from you
try {
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
final SSLContext sslContext = SSLContext.getInstance("TLS");
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream fileInputStream = new FileInputStream(new File("cert.pk12"))) {
keyStore.load(fileInputStream, certPassword);
} catch (final Exception e) {
logger.error("....", e);
}
this.readLoadCertificateFile(keyStore);
kmf.init(keyStore, certPassword);
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{new AnyTrust()}, null);
return sslContext.getSocketFactory();
} catch (Exception e) {
logger.error(".....", e);
}
throw new IllegalStateException("....");
}
HTTPRequest req = ....
req.setSSLSocketFactory(getSSLSocketFactory());
tokenHttpResp = req.send();`
`
一切似乎都很好,但是当我从WF16内部运行此代码时,它会抛出
IOException:无法加载.p12密钥库:C:\ Cert \ cert.p12;错误 构造MAC:java.lang.SecurityException:JCE无法认证 提供者BC; org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.engineLoad ::-1 KeyStore.java::1445中的java.security.KeyStore.load
我检查了充气城堡库,但应用程序本身没有它... 如果有人知道是什么问题,我将不胜感激。
或者,我希望将此套接字工厂创建的内容移入容器本身,似乎是Wildfly Elytron子系统专门为此设计的,这是个好主意吗?
答案 0 :(得分:0)
回答我自己的问题。 诸如“ JCE无法验证提供者BC ”之类的错误消息表明JVM无法验证从中加载了安全提供者的jar文件。罐子未签名或签名无法验证。以我为例,较新的Wildfly版本具有较新版本的Bouncy Castle库,由于某些原因,它无法通过Java 8进行验证。有趣的是,对于Java 10来说还可以。一些Internet上的人说,仅此问题发生在Oracle的JVM中,并且对于Open JDK不存在,我尚未对其进行测试,只是认为值得一提。
要解决此问题,您需要告诉JVM信任安全提供程序,为此,请确保要使用的安全提供程序/ JVM已决定使用,如 jre / lib / security / java.security中所述文件,它应具有以下行:
security.provider.11 = org.bouncycastle.jce.provider.BouncyCastleProvider
然后将Jars with Security Provider复制到 / jre / lib / ext 文件夹