Можно ли заставить Java игнорировать хранилище доверенных сертификатов и просто принимать любой сертификат SSL, который он получает?

Я пытаюсь написать клиент SSL, который отправляет почту с использованием API javax.mail. Проблема, с которой я сталкиваюсь, заключается в том, что сервер запрашивает использование SSL, но сервер также настроен с нестандартным сертификатом SSL. На веб-страницах, которые я нашел, говорится, что мне нужно установить сертификат в хранилище доверенных сертификатов. Я не хочу этого делать (у меня нет необходимых разрешений).

  1. Есть ли способ заставить Java просто игнорировать ошибку сертификата и принять ее?
  2. В противном случае есть ли способ сделать так, чтобы хранилище доверия было локальным для моей программы, а не устанавливалось для всей JVM?

person vy32    schedule 02.08.2009    source источник
comment
Просто чтобы уточнить, вы можете изменить код сервера или только клиента?   -  person Bill the Lizard    schedule 02.08.2009
comment
Игнорировать этап проверки сертификата — плохая идея. Вряд ли есть смысл говорить тайно с кем-то, если вы не уверены, кто это. Вариант 2 (локальное хранилище доверия) достаточно прост в использовании.   -  person Bruno    schedule 18.01.2012
comment
Игнорирование шага проверки допустимо в некоторых обстоятельствах, например, если вы находитесь в изолированной сети, и SSL является единственной включенной службой не из-за политики, а потому, что ваш администратор не знает, как включить службу без SSL.   -  person vy32    schedule 19.01.2012
comment
Я не думаю, что это хорошая идея - обходить проверку хранилища доверенных сертификатов. Особенно, если удаленный сервер находится вне вашего контроля. В вашем случае может возникнуть проблема с самоподписанным сертификатом. Если вы подтвердили эмитента, вы можете просто добавить его в хранилище доверенных сертификатов с помощью keytool. Это лучше, чем использование собственного TrustManager, который принимает сертификаты вслепую.   -  person Awan Biru    schedule 23.10.2018


Ответы (5)


Вам нужно создать поддельный TrustManager, который принимает все сертификаты, и зарегистрировать его в качестве менеджера. Что-то вроде этого:

public class MyManager implements com.sun.net.ssl.X509TrustManager {
  public boolean isClientTrusted(X509Certificate[] chain) { return true; }
  public boolean isHostTrusted(X509Certificate[] chain) { return true; }
  ...
}


com.sun.net.ssl.TrustManager[] managers =
  new com.sun.net.ssl.TrustManager[] {new MyManager()};

com.sun.net.ssl.SSLContext.getInstance("SSL").
       .init(null, managers, new SecureRandom());
person Zed    schedule 02.08.2009
comment
Все это действительно нужно делать с помощью общедоступного API JSSE, а не настраивать скрытые com.sun.* классы. (См. ответ so_mv.) - person Bruno; 18.01.2012

Рабочий код (в jdk1.6.0_23) для #1.

Импорт

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

Фактическое доверие всему коду TrustManager.

TrustManager trm = new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType) {

    }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { trm }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
person so_mv    schedule 15.04.2011
comment
Спасибо, это отлично сработало для меня. Единственная проблема с этим заключается в том, что он глобально устанавливает настройки для доверия любым сертификатам.... Более безопасным подходом может быть возврат URLConnection к HttpsURLConnection и вызов setSSLSocketFactory для этого. Тем не менее, это БОЛЬШОЙ ответ, несколько других сказали, что невозможно обойти проверку доверия, и необходимо добавить сертификат или настроить некоторые параметры JVM. - person Cervo; 28.04.2012
comment
Это также может понадобиться, если имя хоста не соответствует сертификату: HostnameVerifier nullVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier (nullVerifier); - person seanf; 09.01.2013
comment
Этот ответ следует принять, так как он не использует пакеты, специфичные для солнца. - person Kumar Vaibhav; 26.03.2018
comment
В моем случае помогло заставить клиента использовать TLSv1 вместо TLS1.2. См. этот пост: stackoverflow.com/a/30455363/2239549 - person vivanov; 14.12.2018
comment
Вы можете захотеть, чтобы getAcceptedIssuers() возвращал новый X509Certificate[0] вместо null, если вы используете более новые версии OkHttp. В противном случае это приведет к исключению NullPointerException. - person Kutzi; 10.01.2019

Попробуйте это (ответ на вопрос 2):

System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore");

Вы также можете указать это как дополнительный параметр командной строки:

java -Djavax.net.ssl.trustStore=/path/to/truststore <remaining arguments>

В Fedora это может быть общесистемное хранилище доверия Java в /etc/pki/java/cacerts.

person H Marcelo Morales    schedule 02.08.2009
comment
есть ли способ указать доверять всем как 2-й аргумент, например, используя * и т. д.? - person Umer Hayat; 09.07.2012
comment
@UmerHayat Нет. Вы должны кодировать, как в двух других ответах. - person H Marcelo Morales; 09.07.2012

Просто добавьте -Dtrust_all_cert=true к аргументам виртуальной машины. Этот аргумент указывает java игнорировать все проверки сертификатов.

person Ayman Hussain    schedule 21.11.2016
comment
Это довольно пугающе, но кажется хорошим ответом! Однако я хотел бы сделать это в Java и, возможно, иметь немного больше контроля в будущем. - person vy32; 21.11.2016
comment
Это не аргумент VM и в целом не сработает. - person René; 06.03.2017
comment
Я пытался. Это работает на JDK8. Это действительно полезно, когда вы доверяете всем URL-адресам, которые использует JVM. например Инструмент проверки зависимостей OWASP - person UmeshPathak; 16.01.2020

В командной строке вы можете добавить аргумент -noCertificationCheck в java, чтобы игнорировать проверки сертификата.

person Navaneetha    schedule 31.07.2017
comment
Какой кли? где? и при чем здесь этот аргумент? - person Kumar Vaibhav; 26.03.2018
comment
В какой версии Явы? Потому что не на Java 8. Этот аргумент не распознается и не позволяет загрузить Java. - person Javier Paz Sedano; 17.05.2019