2012-01-30 5 views
5

У меня проблемы с взаимодействием с сайтом HTTPS через Java. Моя программа использует один URL-адрес с ненадежным сертификатом каждый раз, когда программа запускается. Эта программа должна работать на нескольких системах. В настоящее время у меня есть следующие:Прием сертификатов в Java

public class A{ 
    HostnameVerifier hv = new HostnameVerifier(){ 
     public boolean verify(String urlHostName, SSLSession session){ 
      return true; 
     }  
    }; 

    HttpsURLConnection.setDefaultHostnameVerifier(hv); 

    javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; 
    javax.net.ssl.TrustManager tm = new miTM(); 
    trustAllCerts[0] = tm; 
    javax.net.ssl.SSLContext sc = null; 
    try { 
     sc = javax.net.ssl.SSLContext.getInstance("SSL"); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
    try { 
     sc.init(null, trustAllCerts, null); 
    } catch (KeyManagementException e) { 
     e.printStackTrace(); 
    } 
    javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
} 
class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager{ 

    public java.security.cert.X509Certificate[] getAcceptedIssuers(){ 
     return null; 
    } 

    public boolean isServerTrusted(java.security.cert.X509Certificate[] certs){ 
     return true; 
     } 

    public boolean isClientTrusted(java.security.cert.X509Certificate[] certs){ 
     return true; 
    } 

    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException{ 
     return; 
    } 

    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException{ 
     return; 
     } 
} 

С помощью этого кода можно выполнить следующие действия просто отлично:

URL url = new URL(urlString); 
URLConnection cnx = url.openConnection(); 
cnx.connect(); 

InputStream ins = cnx.getInputStream(); 
BufferedReader in = new BufferedReader(new InputStreamReader(ins)); 
String curline; 
while((curline = in.readLine()) != null) { 
    System.out.println(curline); 
} 

Однако, я не могу сделать следующее:

httpClient = new HttpClient(); 
PostMethod postMethod = null; 
int intResult = 0; 
postMethod = new PostMethod(authURL); 
Enumeration emParams = authParams.propertyNames(); 
while (emParams.hasMoreElements()) { 
    String paramName = (String) emParams.nextElement(); 
    String paramValue = authParams.getProperty(paramName); 
    postMethod.addParameter(paramName, paramValue); 
} 

intResult = httpClient.executeMethod(postMethod); 
postMethod.releaseConnection(); 
ins.close(); 

Когда ExecuteMethod (postMethod), я получаю SSLHandshakeException, CertPathBuilderException и т. д.

Что делать, чтобы исправить это? Я думаю либо принять сертификат, либо просто обойти всю проверку сертификата (поскольку программа выполняется внутри частной сети).

Благодаря

+0

Вы используете Apache HttpClient 3.x (или 4)? – Bruno

ответ

5

Похоже, что вы используете Apache HttpClient 3. Если это действительно вариант 3, вам нужно создать свой собственный SecureProtocolSocketFactory, как описано в Apache HttpClient 3 SSL guide. Существует example here.

Для Apache HTTPClient 4, вы должны быть в состоянии передать SSLContext конструктору к (HttpClient) SSLSocketFactory, как описано в the answers to this question (включая примечания относительно хоста имя проверки).

Однако, вообще говоря, не следует этому подходу. Вы фактически отключите часть аутентификации SSL/TLS, сделав это, тем самым сделав ее уязвимой для атак MITM.

Вы должны явно импортировать сертификат сервера в хранилище доверия клиента, как описано в this answer.

Я имею в виду либо принять сертификат или просто обходя все проверки сертификата (как программа работает внутри в частной сети).

Что вы говорите, так это то, что вы готовы использовать SSL/TLS для шифрования только в своей частной сети, потому что вы не доверяете своим пользователям достаточно, чтобы не смотреть на трафик, который может обойти их машины , но вы также предполагаете, что эти пользователи не смогут выполнить атаку MITM. Это не совсем понятно. Если вы доверяете им достаточно, вы можете также отправить данные в ясный. Если вы этого не сделаете, вы должны правильно реализовать SSL/TLS, включая шаги аутентификации (проверка сертификата и проверки имени хоста).

+0

Спасибо! Я использовал Apache HttpClient 3.x, но решил пойти с 4. Я следил за вашими рекомендациями, и это сработало. Еще раз спасибо. – ms1013

1

HttpClient 4.3:

 HttpClientBuilder cb = HttpClientBuilder.create(); 
    SSLContextBuilder sslcb = new SSLContextBuilder(); 
    sslcb.loadTrustMaterial(KeyStore.getInstance(KeyStore.getDefaultType()), new TrustSelfSignedStrategy()); 
    cb.setSslcontext(sslcb.build()); 
    CloseableHttpClient httpclient = cb.build(); 
+0

Не могли бы вы немного объяснить это? – benka

Смежные вопросы