【发布时间】:2018-10-05 12:29:36
【问题描述】:
在我们的应用程序中,我们通过 HTTPS 对身份验证服务进行 HTTP 调用。 我需要确保我们进行所有必要的检查以确保连接安全。作为其中的一部分,我必须实现以下内容:
- 验证身份验证服务器的证书是否由知名 CA 颁发。
- 验证身份验证服务器证书中存在的主机名是否与我们用于连接身份验证服务器的主机名匹配。
我对第 1 项没有任何问题。
对于第 2 项,我正在尝试使用 HostNameVerifier 实现。
到目前为止我的代码:
package com.company;
import sun.security.x509.X500Name;
import javax.net.ssl.*;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class Main {
public static void main(String[] args) throws Exception {
URL endpoint = new URL("https://example.com");
HttpsURLConnection conn = (HttpsURLConnection) endpoint.openConnection();
conn.setHostnameVerifier(new MyHostNameVerifier());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {trustAll}, null);
conn.setSSLSocketFactory(sslContext.getSocketFactory());
System.out.println("HTTP Response: " + conn.getResponseCode());
}
public static final X509TrustManager trustAll = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
public static class MyHostNameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostName, SSLSession sslSession) {
System.out.println("*** Validating host name for " + hostName);
return false;
}
}
}
我的期望是 MyHostNameVerifier#verify 将始终被调用,并且我可以在那里进行某些检查。
但是,我发现 HostNameVerifier#verify 方法仅在我使用站点的 IP 地址时调用,或者仅当主机名与证书的主题或任何主题备用名称不匹配时调用。
HostNameVerifier#verify 在下列情况下不会被调用:
- 如果站点的证书是通配符证书,并且它与使用的主机名匹配。
- 如果站点的证书是 SAN 证书,并且我使用的主机名是使用者的 CN 或列为使用者备用名称值之一。
例如:
在上面的代码中,我试图连接到“example.com”。
“example.com”的SSL证书颁发给CN“www.example.org”。
但是,“example.com”列在证书的“主题备用名称”(SAN) 中。
如果我改为使用“example.com”的 IP 地址,则会调用我的主机名验证程序。
URL endpoint = new URL("https://93.184.216.34/");
谁能向我确认 Java 在内部处理通配符证书和 SAN 证书检查?如果是,那么,我可能不需要做任何额外的代码更改。
【问题讨论】:
标签: java security ssl-certificate