2020年4月1日 更新:
解決在OpenJDK11下Spring Boot FatJar拋出ClassNotFoundException
的問題。詳見Spring Boot Fat Jar 運行異常
問題復現
環境
AD由測試部署在Windows Server 2008上面,服務端證書也是Windows簽發的
客戶端:OpenJDK11(此問題在OpenJDK8+都會出現)
可以直接跳到后面的解決方案
一節查看處理
通過SSL連接LDAP時,會拋出如下異常(精簡后)
1 2 3 4 5 6 7 8 9 10 11
|
javax.net.ssl|DEBUG|01|main|2020-01-05 13:14:47.338 CST|SSLCipher.java:437|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472 ....省略 Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 10.20.61.26 found at java.base/sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:160) at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:96) at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:463) at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:434) at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:233) at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:626) ... 26 more
|
主要就是因為檢查服務端證書的特定擴展失敗,證書中沒有對應的擴展。LDAPS
對應的SSL證書需要驗證IP或者DNS擴展才可以
再看下SSL流的追蹤

最后顯示未知證書
,同時也印證了上面的異常堆棧信息。從而我們知道是證書出的問題
問題分析
定位
證書檢查異常,回過頭去翻一下LDAPS的RFC文檔,在RFC4519第3.1.3.服務端身份認證一節,存在三種認證方式:
都是提取Extensions里面的subjectAlternativeName
(oid: 2.5.29.17
),主要涉及GeneralName
的DNSName
和iPAddress
兩種類型。當證書中不存在相應擴展,或者對應擴展的類型有誤,都會校驗失敗
解決方案
重新實現一個SSLSocketFactory
,不驗證證書等信息即可:
LdapsNoVerifySSLSocketFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.Security; import java.security.cert.CertificateException; import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509ExtendedTrustManager;
|