首页 > 解决方案 > Open Liberty 下的 mpRestClient 证书身份验证握手失败

问题描述

我有一个证书文件,它在一个 Open Liberty 实例(jdk-11.0.5+10-openj9 下的版本 20.0.0.2)下运行良好,可以使用标准 HttpsURLConnection 对使用 cert-auth 的特定端点进行出站调用。在相同版本/JDK 的单独服务器上,我正在使用 MicroProfile REST 客户端 API(如果重要,使用 @Asynchronous)创建一个新应用程序,但调用失败并出现握手失败。我正在使用相同的证书和相同的密钥库配置(并且在两台服务器中都启用了“ssl-1.0”功能)......

<keyStore id="defaultKeyStore" location="key.jks" password="changeit" type="jks"/>

我尝试在两台服务器下使用“-Djavax.net.debug=all”进行调试,发现在服务器启动时在这两种情况下都找到了具有我的目标别名的证书并将其添加为受信任的证书......

SunX509KeyManagerImpl.java:164|found key for : my-alias (...)
X509TrustManagerImpl.java:79|adding as trusted certificates (...)
SSLContextImpl.java:115|trigger seeding of SecureRandom
SSLContextImpl.java:119|done seeding of SecureRandom

但是,对于 mpRestClient 应用程序,当我调用有问题的端点时,它似乎会自发地将信任库切换到默认的 JDK cacerts 信任库......

TrustStoreManager.java:112|trustStore is: C:\Program Files\AdoptOpenJDK\jdk-11.0.5+10-openj9\lib\security\cacerts
....
TrustStoreManager.java:311|Reload the trust store
TrustStoreManager.java:318|Reload trust certs
TrustStoreManager.java:323|Reloaded 88 trust certs
X509TrustManagerImpl.java:79|adding as trusted certificates (...)
SSLContextImpl.java:115|trigger seeding of SecureRandom
SSLContextImpl.java:119|done seeding of SecureRandom

经过一番谈判,最终...

CertificateMessage.java:290|No X.509 certificate for client authentication, use empty Certificate message instead
CertificateMessage.java:321|Produced client Certificate handshake message (
  "Certificates": <empty list>
)
....
TransportContext.java:312|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
  "throwable" : {
    javax.net.ssl.SSLException: readHandshakeRecord
    ....
  }
)

当然,没有为客户端身份验证找到证书,因为重新加载了整个信任库,清除了最初加载的信任库。这种信任存储的自发切换不会在其他服务器下发生。该服务器上相关的成功行为是......

SunX509KeyManagerImpl.java:401|matching alias: my-alias
ServerHelloDone.java:151|Consuming ServerHelloDone handshake message (
  <empty>
)
CertificateMessage.java:321|Produced client Certificate handshake message (...)
SSLSocketOutputRecord.java:241|WRITE: TLS12 handshake, length = 3769
SSLSocketOutputRecord.java:255|Raw write (...)
RSAClientKeyExchange.java:193|Produced RSA ClientKeyExchange handshake message (...)
SSLSocketOutputRecord.java:241|WRITE: TLS12 handshake, length = 262
SSLSocketOutputRecord.java:255|Raw write (...)
CertificateVerify.java:743|Produced CertificateVerify handshake message (...)
SSLSocketOutputRecord.java:241|WRITE: TLS12 handshake, length = 264
SSLSocketOutputRecord.java:255|Raw write (...)
ChangeCipherSpec.java:115|Produced ChangeCipherSpec message
SSLSocketOutputRecord.java:225|Raw write (...)
Finished.java:398|Produced client Finished handshake message (...)
....
ChangeCipherSpec.java:149|Consuming ChangeCipherSpec message
....
SSLSocketInputRecord.java:249|READ: TLSv1.2 handshake, length = 64
SSLCipher.java:1329|Padded plaintext after DECRYPTION (...)
Finished.java:535|Consuming server Finished handshake message (...)
SSLSocketOutputRecord.java:309|WRITE: TLS12 application_data, length = 339
SSLCipher.java:1483|Padded plaintext before ENCRYPTION (...)
SSLSocketOutputRecord.java:323|Raw write (...)
...
SSLSocketInputRecord.java:249|READ: TLSv1.2 application_data, length = 544
SSLCipher.java:1329|Padded plaintext after DECRYPTION (...)
[...and then I get my decrypted response...]

两种服务器设置之间的另一个区别是,成功的一个是 Open Liberty 的 javaee8 版本的独立下载,而不成功的一个是通过 Maven 执行的......

mvn liberty:dev -Ddebug=false -DskipTests=true

我不知道为什么这会产生任何影响,但很明显。配置的设置几乎相同。我一直在四处寻找,并尝试了我能想到的一切来修补,但现在我对可能产生的影响感到茫然。希望有人注意到一些事情。关键是让运行 mpRestClient 应用程序的服务器停止自发地将信任存储切换到 JDK cacerts 默认值。但到目前为止,我没有尝试过阻止这种情况。

标签: javasslopen-liberty

解决方案


最终,我认为这是一个错误,所以我建议您在https://github.com/OpenLiberty/open-liberty/issues上打开一个问题(请务必参考此页面)。我认为您可以通过添加 appSecurity-2.0 功能来解决此问题。似乎 JAX-RS 需要 SSL 和 AppSecurity 功能才能使用不同的密钥存储。appSecurity-2.0这解释了 ClassNotFoundException - 如果安装了(或 3.0)特性,JaxRsSSLManager 类只会添加到框架的类路径中。

使用 AppSecurity 功能应该可以解决问题,但我认为这是一种解决方法。如果您打开 OpenLiberty 的问题,我们可以尝试在没有 AppSecurity 功能的情况下使其正常工作。

希望这会有所帮助,安迪


推荐阅读