2013-06-12 4 views
3

Java에서 POST 요청을 수행하려고합니다. 나는 HTTP로 succeded,하지만 HTTPS는 나를 위해 까다 롭습니다.제목 대체 DNS 이름 일치

// 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()); 

, 그것은 사이트 등 신뢰할 수없는 인증서를 사용하고 있다고 나는 파이어 폭스에서 내 테스트 웹 페이지 https://requestb.in/191g0961를로드 할 때 때문에, 내 문제를 해결 희망의 TrustManager를 추가했습니다 ..

: 은이 코드를 사용하고

내 코드는이 페이지를 좋아합니다, 어떤 경고없이 파이어 폭스에로드 된 페이지와 함께 작동 : https://extranet.nix.cz/login

을 (당신은 그것을 시도 할 수 있습니다)하지만 https://requestb.in/191g0961으로 나에게 다음과 같은 예외주고있다 :

,691,363을210
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()); 
+0

'TrustManager'의 메소드가 호출되었는지 확인 했습니까? 특히 checkServerTrusted() 메소드가 필요하다. –

+0

방금 ​​시도해 본 결과'checkServerTrusted()'메소드가 실제로 호출되었습니다. – Firzen

답변

8

당신은 또한 HttpsURLConnectionHostnameVerifier을 설정해야합니다. 이것은 구현에 의해 호스트 이름이 받아 들여지는지 확인해야합니다.

이 코드는 모든 보안을 비활성화 할 가능성이 있으므로 프로덕션 환경에서는이 코드를 사용하지 않는 것이 좋습니다.

+0

정말 대단합니다! 그것은 완벽하게 작동합니다. 고맙습니다! – Firzen