Open Liberty 下的 mpRestClient cert auth 握手失败

mpRestClient cert auth handshake failure under Open Liberty

我有一个证书文件在一个 Open Liberty 实例(jdk-11.0.5+10-openj9 下的版本 20.0.0.2)下运行良好,使用标准 HttpsURLConnection 进行出站调用,以使用 cert-auth 的特定端点。在同一 version/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 默认值。但到目前为止,我没有尝试过阻止这种情况。

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

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

安迪,希望这对您有所帮助