java 没有主题替代 DNS 名称匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17060717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
No subject alternative DNS name matching
提问by Firzen
I am trying to perform POST request in Java. I have succeded with HTTP, but HTTPS is tricky for me. I am using this code:
我正在尝试用 Java 执行 POST 请求。我已经成功使用 HTTP,但 HTTPS 对我来说很棘手。我正在使用此代码:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
String httpsURL = "https://requestb.in/191g0961";
String query = "email="+URLEncoder.encode("[email protected]","UTF-8");
query += "&";
query += "password="+URLEncoder.encode("abcd","UTF-8") ;
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-length", String.valueOf(query.length()));
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream output = new DataOutputStream(con.getOutputStream());
output.writeBytes(query);
output.close();
DataInputStream input = new DataInputStream(con.getInputStream());
for( int c = input.read(); c != -1; c = input.read() )
System.out.print( (char)c );
input.close();
System.out.println("Resp Code:"+con .getResponseCode());
System.out.println("Resp Message:"+ con .getResponseMessage());
I have added TrustManager in hope it solves my problem, because when I load my testing webpage https://requestb.in/191g0961in Firefox, it says that site uses untrusted certificate, etc..
我添加了 TrustManager 希望它能解决我的问题,因为当我在 Firefox 中加载我的测试网页https://requestb.in/191g0961时,它说该站点使用不受信任的证书等。
My code works with pages that are loaded in Firefox without any warnings, like this page: https://extranet.nix.cz/login(you can try it)
我的代码适用于在 Firefox 中加载的页面,没有任何警告,比如这个页面:https: //extranet.nix.cz/login(你可以试试)
But with https://requestb.in/191g0961it is giving me following exceptions:
但是使用https://requestb.in/191g0961它给了我以下例外:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching requestb.in found.
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at https.Sender.main(Sender.java:80)
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching requestb.in found.
at sun.security.util.HostnameChecker.matchDNS(Unknown Source)
at sun.security.util.HostnameChecker.match(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(Unknown Source)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source)
... 13 more
Have you any ideas how to solve this? Thanks in advance!
你有什么想法如何解决这个问题吗?提前致谢!
Solution:
解决方案:
I have created this simple class:
我创建了这个简单的类:
public class Verifier implements HostnameVerifier {
public boolean verify(String arg0, SSLSession arg1) {
return true; // mark everything as verified
}
}
and then I added:
然后我补充说:
con.setHostnameVerifier(new Verifier());
回答by Uwe Plonus
You also have to set a HostnameVerifier
in the HttpsURLConnection
. This has to verify that the hostname is accepted by your implementation.
您还必须HostnameVerifier
在HttpsURLConnection
. 这必须验证您的实现是否接受主机名。
I also suggest to not use this code in production environment as this code is likely to disable all security.
我还建议不要在生产环境中使用此代码,因为此代码可能会禁用所有安全性。