2017-02-14 2 views
1

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

StringBuilder sb = new StringBuilder(); 
     URL oracle = new URL("https://company.com"); 
     URLConnection yc = oracle.openConnection(); 
     BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); 
     String inputLine; 
     while ((inputLine = in.readLine()) != null) 
      sb.append(inputLine); 
     in.close(); 
     return sb.toString(); 

Я получаю

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) 
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) 
    at sun.security.validator.Validator.validate(Validator.java:260) 
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) 
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) 
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) 
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491) 

Если я использую http://company.com вместо он работает, но я хочу использовать https one, потому что это то, что они говорят, чтобы использовать, и я думаю, что небезопасный может быть удален.

Однако, когда я просмотрел похожие ответы об этом, он говорит о копировании сертификатов из моего браузера ectera. Мне нужно решение, которое будет работать для всех, кто запускает код на любом компьютере, не делая ничего особенного.

Я не беспокоюсь о преимуществах безопасности SSL для этого проекта. Я просто хочу иметь возможность подключиться к wenbsite.

+3

«Не беспокоясь о« SSL », вы говорите, что вам неинтересно, что ваша программа обманута атаками« человек в середине », хотя рассматриваемый сайт четко * делает * заботиться о человеке- in-the-middle (если они говорят, что используют версию https и что http-версия может быть удалена в какой-то момент). –

+0

Во-первых, если сайт не предлагает HTTP, вы все равно потерпите неудачу. Во-вторых, ваш запрос должен работать, поскольку среда выполнения имеет хранилище [хранилище доверия] по умолчанию (http://stackoverflow.com/questions/1398556/connect-to-https-siteserver). Возможно, сертификат на этом веб-сайте имеет проблемы и не может быть подтвержден. – Alfabravo

+0

@ T.J.Crowder посмотрите, если они не предоставили версию https, вы бы не говорили мне, чтобы я не использовал сайт, нет ничего критического/чувствительного к данным. Поэтому вместо того, чтобы критиковать меня за то, что я не беспокоился о ssl в thsi cirumstance, как я могу решить проблему –

ответ

1

Кажется, вас уже предупредили против подхода, поэтому я буду отвечать на ваш вопрос. Я смог воспроизвести проблему на своей машине, хотя я не могу сказать почему: Мой браузер принимает сертификат сайта без заминки.

Я попытался расширить свой код, чтобы он работал, но вскоре обнаружил, что я возился с SSLContext, различными крипто-провайдерами и интерфейсами поставщика услуг. Мне не удалось выполнить этот подход и на самом деле не рекомендую идти таким путем, так как он изменяет глобальные параметры безопасности вашей JVM и может иметь непредсказуемые последствия в зависимости от того, что еще он делает.

Вместо этого я предлагаю вам взглянуть на Apache HttpComponents library, что позволяет более точно контролировать параметры безопасности соединения.

Ниже будет отключить все проверки сертификата для созданного HttpClient экземпляра:

TrustStrategy veryNaive = new TrustStrategy() { 
    @Override 
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
     return true; 
    } 
}; 

SSLContext sslcontext = SSLContexts.custom() 
    .loadTrustMaterial(veryNaive) 
    .build(); 

CloseableHttpClient httpclient = HttpClients.custom() 
    .setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext)) 
    .build(); 

try { 
    HttpGet httpget = new HttpGet("https://company.com"); 

    try (CloseableHttpResponse response = httpclient.execute(httpget);) { 
     HttpEntity entity = response.getEntity(); 
     System.out.println(EntityUtils.toString(entity)); 
     EntityUtils.consume(entity); 
    } 
} finally { 
    httpclient.close(); 
} 

Изменение SSLContext к SSLContexts.createSystemDefault(); повторно вводит проблему, просто чтобы показать, что это также присутствует в библиотеке Apache.

+0

благодарю вас за решение, у меня есть одна проблема, хотя я использую HttpComponents 4.5.3 и SSLContexts.custom(). LoadTrustMaterial(), кажется, требует доверия, а не truststrategy? –

+0

@PaulTaylor: Убедитесь, что вы используете правильный. Кажется, что библиотека содержит два класса SSLContexts, один из которых устарел. Правильным является 'org.apache.http.ssl.SSLContexts' (http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/ssl/SSLContexts.html). – Henrik

+0

спасибо, что работает. Моя единственная проблема заключается в том, что иногда url-поиск не существует, и ваш код не справляется с этим, поскольку он возвращает некоторый json, указывающий не найденный, а не возвращающий ничего/выдающий код ошибки, который отличается от моего http (без защищенного) случая , –

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