没有主题替代DNS名称匹配

时间:2013-06-12 08:15:03

标签: java post https

我正在尝试用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("abc@xyz.com","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());

我已经添加了TrustManager,希望它能解决我的问题,因为当我在Firefox中加载我的测试网页https://requestb.in/191g0961时,它说该网站使用不受信任的证书等。

我的代码适用于在Firefox中加载的页面,没有任何警告,例如此页面:https://extranet.nix.cz/login(您可以尝试)

但是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

您有任何想法如何解决这个问题? 提前谢谢!

解决方案:

我创建了这个简单的类:

public class Verifier implements HostnameVerifier {

    public boolean verify(String arg0, SSLSession arg1) {
            return true;   // mark everything as verified
    }
}

然后我补充说:

con.setHostnameVerifier(new Verifier());

1 个答案:

答案 0 :(得分:9)

您还必须在HostnameVerifier中设置HttpsURLConnection。这必须验证您的实现是否接受主机名。

我还建议不要在生产环境中使用此代码,因为此代码可能会禁用所有安全性。