I'm using a HttpURLConnection in order create a POST request (for fetching a token at some OAuth2 token endpoint). The token endpoint uses HTTPS. I wonder how the hostname verification with regards to HTTPS works. The default hostname verifier of HttpsURLConnection seems to be the following [1]:
/**
* HostnameVerifier provides a callback mechanism so that
* implementers of this interface can supply a policy for
* handling the case where the host to connect to and
* the server name from the certificate mismatch.
*
* The default implementation will deny such connections.
*/
private static HostnameVerifier defaultHostnameVerifier =
new HostnameVerifier() {
public boolean verify(String urlHostname, String certHostname) {
return false;
}
};
Run Code Online (Sandbox Code Playgroud)
I expected my POST request to fail as this verifier always returns false. This is not the case. The comment already states that there is some kind of callback mechanism. What I do not know is: Does the defaultHostnameVerifier verify the hostname of the connection and the certificate or is it rather a dummy implementation?
My current coding looks like the following piece:
private HttpURLConnection openConnection(String url) throws IOException {
URL urly = new URL(url);
final HttpURLConnection con;
Proxy proxy = getProxy();
if (proxy == null) {
con = (HttpURLConnection) urly.openConnection();
} else {
con = (HttpURLConnection) urly.openConnection(proxy);
}
if (con instanceof HttpsURLConnection) {
HostnameVerifier verifier = ((HttpsURLConnection) con).getHostnameVerifier(); // there is a default set
System.out.println(verifier.getClass().getName());
}
return con;
}
Run Code Online (Sandbox Code Playgroud)
I've found some explanation with regards to the AsyncHttpClient [2]. As I do not use it at this point of time am I safe going with the default implementation?
正如顶部的评论所说,该类不再使用;它是抽象的用户可见类,现在已被javax.net.HttpsURLConnection取代,您将观察到它具有相同的代码。但是https URL的实现类是sun.net.www.protocol.https.HttpsURLConnectionImpl,它只是包装(委托给)sun.net.www.protocol.https.DelegateHttpsURLConnection,它是sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection的子类要进行实际连接,请使用sun.net.www.protocol.HttpsClient,特别是 .afterConnect()。作为背景,在早期版本的Java中SSLSocket没有进行主机名验证,因此HttpsURLConnection的实现必须添加它。在 Java 7 及以上版本中,SSLSocket确实支持“端点识别”,因此当 afterConnect() 识别出此 URLconnection 上的主机名验证器是默认值时,它会关闭needToCheckSpoofing并设置SSLSocket进行端点识别。
javax.net.ssl.SSLSocket类似地是一个抽象类,实际上由sun.security.ssl.SSLSocketImpl和几十个相关类实现,包括sun.security.ssl.ClientHandshaker.serverCertificate(),它调用可配置的 trustmanager,默认情况下是sun.security.ssl.X509TrustManagerImpl在checkTrusted()中,因为请求了端点标识,所以调用checkIdentity(),后者使用TYPE_TLS 调用sun.security.util.HostnameChecker(实际上意味着 HTTPS RFC 2818),并执行实际检查。
很高兴你问了?
PS:该网页上的分析认为,仅因不匹配而调用 HttpsURLConnection.DefaultHostnameVerifier,这是完全错误的。如上所述,它被绕过并且从未被实际实现调用。
另外,我假设您意识到 java 7 多年来一直不受支持,除非您付费。尽管据我所知,在最近的版本中这个区域没有改变。Java 11 确实添加了一个新的 java.net.http.HttpClient,它在功能上取代了 [Http,Https]URLConnection。
| 归档时间: |
|
| 查看次数: |
2866 次 |
| 最近记录: |