记录一次https通讯调试过程
写在前面,感谢无数工程师的无私奉献,本文是基于网上文章分享得出的解决办法。
情况说明:和服务端https交互时,用域名的方式会有正常的应答,用指定IP的方式则提示异常。
代码抛出异常如下:
javax.net.ssl.SSLHandshakeException:Remote host closed connection during handshake at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl,java:882) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSSocketImpl.java:1188) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSSocketImpl.java:654) at com.sun.net.ssl.internal.ssl.AppOutputstream.write(AppOutputstream.java:100) at org.apache.http.impl.io.AbstractSessionoutputbuffer.flushBuffer(AbstractSessionOutputBuffer java:131) [httpcore-4 1.4.jar:4.1.4)
用curl测试如下:
curl -X Post -H "Content-Type:application/json" "https://www.zjoj.com.cn:5858/api/Bank/SaveBankAccount?appid=10016" {"data":false,"code":104,"message":"Object reference not set to an instance of an object."}
curl -X Post -H "Content-Type:application/json" "https://121.41.60.113:5858/api/Bank/SaveBankAccount?appid=10016" curl: (60) schannel: SNI or certificate check failed: SEC_E_WRONG_PRINCIPAL (0x80090322) - 目标主要名称不正确。 More details here: https://curl.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above.
在idea使用JetClient,测试结果如下:
报错信息为"Certificate for 121.41.60.113> doesn't match any of the subject alternative names:[]"
经查阅资料,了解一般请求方在交互过程中,会校验证书包含的一些信息,其中会有目标域和证书中的CN是否匹配,如下:
[下载服务端公钥证书命令:openssl s_client -connect www.zjoj.com.cn:5858 或者 openssl s_client -connect 121.41.60.113:5858 ]
由于直接指定IP时,IP和CN值不匹配,导致证书验证失败,提示交互失败。
解决办法:
- 直接使用域名访问;
- 使用指定IP访问时,自定义变量Host为域名的值,这样校验时就会用Host的值与证书的CN值做比较;
- 代码里不对证书CN值做校验(不推荐,有安全风险)
写在后面:
由于当前项目使用的jdk版本为1.6,不支持一些协议算法,比如TLS(SSL协议的升级版),解决办法如下:
- 可以考虑手工将所需算法补充到当前jdk中,
- 或者引用三方的BouncyCastle包可以解决,
- 或者直接升级jdk到idk1.8.0 162及更高版本。
我是一个小小的搬运工,让米粒变成仓廪