关于HttpsURLConnection的一个问题
最近使用Hutool进行https连接的时候,发现部分网站无法进行连接的问题,而使用以前的方法进行连接却可以。例如,访问Hutool的官网https://www.hutool.club,会报下面的错误:
代码:
HttpRequest get = HttpRequest.get("https://www.hutool.club");
HttpResponse execute = get.execute();
System.out.println(execute.body());
报错:
Exception in thread "main" cn.hutool.http.HttpException: Received fatal alert: internal_error
at cn.hutool.http.HttpRequest.send(HttpRequest.java:920)
at cn.hutool.http.HttpRequest.execute(HttpRequest.java:804)
at cn.hutool.http.HttpRequest.execute(HttpRequest.java:778)
at com.lyf.view.Test.main(Test.java:342)
Caused by: javax.net.ssl.SSLException: Received fatal alert: internal_error
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at cn.hutool.http.HttpConnection.connect(HttpConnection.java:447)
at cn.hutool.http.HttpRequest.send(HttpRequest.java:917)
... 3 more
在网上找了一下这个错误,没发现有用的信息。然后从代码中排除错误,复原了一份Hutool对HttpsURLConnection的操作,大概像下面这样:
URL url = new URL("https://www.hutool.club");
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setHostnameVerifier(new TrustAnyHostnameVerifier());
httpUrlConn.setSSLSocketFactory(new AndroidSupportSSLFactory());
httpUrlConn.setDoInput(true);
httpUrlConn.connect();
通过与以前代码的对比,发现是“httpUrlConn.setHostnameVerifier(new TrustAnyHostnameVerifier());”这一行出了问题,如果不加这一行的话,是可以进行连接的。这就比较奇怪了。因为TrustAnyHostnameVerifier的实现是这样的:
public class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;// 直接返回true
}
}
这里默认是不进行主机校验的,那么再来看看默认的校验方式:
URL url = new URL("https://www.hutool.club");
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
System.out.println(httpUrlConn.getHostnameVerifier());
打印结果:
javax.net.ssl.HttpsURLConnection$DefaultHostnameVerifier@c41709a
发现默认的使用的是HttpsURLConnection.defaultHostnameVerifier。既然这样,我手动把有问题的那一行换成httpUrlConn.setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier());果然就可以正常连接了。
最后,虽然问题已经解决了,但为什么会出现这个问题,目前还不是很清楚,如果有知道的,可以告知一下,谢谢!