Linux 运行 时 Cacerts 文件未应用于 TrustStore

Cacerts file not applied to TrustStore when running on Linux

我在 Linux 环境中将 cacerts 文件的路径设置到 TrustStore 时遇到问题,在 Windows 中运行顺利。

这是一个Spring项目,cacerts文件在资源文件夹中,我通过代码将cacerts路径告知javax.net.ssl.trustStore,我使用命令 mvn clean package 和 linux 创建 .war 文件=], 尝试连接 AD Ldap 服务器时出现错误,我认为问题是没有找到 cacerts。

我用来通知 cacerts 的代码:

Path keystore = null;
try {
    keystore = Files.createTempFile(null, null);

    InputStream stream = getClass().getResourceAsStream("/cacerts");

    Files.copy(stream, keystore, StandardCopyOption.REPLACE_EXISTING);

} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

System.out.println(keystore.toString()); // print path 
System.setProperty("javax.net.ssl.trustStore", keystore.toString());

System.out.println(keystore.toString())显示文件在/tmp中的路径以及当使用 ls -l 检查文件出现在列表中,是 Linux 环境有问题还是应该解决一些代码问题?

已编辑: linux 服务器上出现的错误:

org.springframework.ldap.CommunicationException: 172.16.0.12:636; nested exception is javax.naming.CommunicationException: 172.16.0.12:636 [Root exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 172.16.0.12 found]

I think it could be a code issue.

Some of the JVM properties are used by code that is triggered by static initialization. In this case, the javax.net.ssl.trustStore 属性 is used the first time that something tries to access the default trusted keystore or the default set of trusted X509 certs. It is not clear when this happens.

So, there is a fair chance that your call to System.setProperty is happening too late; i.e. after it has been used.

Try setting the 属性 using a -Djavax.net.ssl.trustStore=... command line option and see if that works.


UPDATE

I've tried with -Djavax.net.ssl.trustStore, it did not work well because it worked "only when it wanted", 10 attempts one worked, approximately! It even that using the -Djavax.net.ssl.trustStore can happen to delay the application of cacerts? On the way this code is executed, the method is an @Bean(name="contextSource") inside an @Configuration class. How can I make to run at the right time?

At least this demonstrates that if you use -D, the 属性 is set early enough to be available. This proves that the mechanism is not broken!

The problem now will be that your custom TrustStore file is being used before app has had a chance to create it. (You could test this ...)

My guess is that it is the web container initilization that is triggering this. I don't think you can make it work1. Instead, you need to address the custom TrustStore requirement in another way:

  • Add a separate deployment step to extract your custom TrustStore to a file in the file system before you start the web container.

  • Alternatively, change the webapp or web container to not rely on the default TrustStore mechanism.

To answer your follow up question: as far as I can tell, there isn't. The Java security code is not designed to allow instantiation of the default TrustStore to be delayed, or to allow it to be changed. Look at the source code!!


1 - Even if you could set the 属性 before the web container initializes and tries to use the TrustStore, you need to first create the TrustStore from a webapp resource. The classloader for that resource is created by webcontainer, during or after the webcontainer initialization. It is most likely to be too complicated to get the steps to reliably happen in the order that you need them to.

关于IP的问题,我是在执行.war文件的时候加上参数解决的。

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true