Игнорировать самозаверяющий сертификат ssl с помощью клиента Jersey
Я использую клиентскую библиотеку Jersey для запуска тестов против службы rest, работающей на jboss.
У меня https настроен отлично на сервере (работает на localhost), используя самозаверяющий сертификат.
однако всякий раз, когда я запускаю свои тесты с url https, я получаю следующую ошибку:
com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131)
at com.sun.jersey.api.client.Client.handle(Client.java:629)
at com.sun.jersey.oauth.client.OAuthClientFilter.handle(OAuthClientFilter.java:137)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:601)
at com.sun.jersey.api.client.WebResource.access0(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:459)
at test.helper.Helper.sendSignedRequest(Helper.java:174)
... And so on
Я знаю, что это потому, что мой самозаверяющий сертификат не находится в хранилище ключей java. Есть ли способ, которым я могу сделать Client Не проверяйте действительность сертификата ssl и просто используйте его все равно?
этот код будет выполняться только на тестовых серверах, поэтому я не хочу тратить время на добавление новых доверенных сертификатов каждый раз, когда мы устанавливаем новый тестовый сервер.
вот код, который делает вызов:
OAuthParameters params = new OAuthParameters();
// baseline OAuth parameters for access to resource
params.signatureMethod(props.getProperty("signature_method"));
params.consumerKey(props.getProperty("consumer_key"));
params.setToken(props.getProperty("token"));
params.setVersion("1.0");
params.nonce();
// OAuth secrets to access resource
OAuthSecrets secrets = new OAuthSecrets();
secrets.consumerSecret(props.getProperty("consumer_secret"));
secrets.setTokenSecret(props.getProperty("token_secret"));
// Jersey client to make REST calls to token services
Client client = Client.create();
// OAuth test server resource
WebResource resource = client.resource(props.getProperty("url"));
// if parameters and secrets remain static, filter cab be added to each web resource
OAuthClientFilter filter = new OAuthClientFilter(client.getProviders(), params, secrets);
// filter added at the web resource level
resource.addFilter(filter);
WebResource.Builder wbr = resource.getRequestBuilder().accept(props.getProperty("accept"));
return wbr.get(ClientResponse.class);
любая помощь будет высоко оценили.
11 ответов:
после некоторого поиска и траления через некоторые старые вопросы stackoverflow я нашел решение в ранее заданном вопросе SO:
вот код, который я в конечном итоге использовал.
// Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){return null;} public void checkClientTrusted(X509Certificate[] certs, String authType){} public void checkServerTrusted(X509Certificate[] certs, String authType){} }}; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { ; }
Для Джерси 2.* (Проверено на 2.7) и java 8:
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public static Client ignoreSSLClient() throws Exception { SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); return ClientBuilder.newBuilder() .sslContext(sslcontext) .hostnameVerifier((s1, s2) -> true) .build(); }
У меня была та же проблема adn не хотел, чтобы это было установлено глобально, поэтому я использовал тот же код TrustManager и SSLContext, что и выше, я просто изменил клиент, который будет создан со специальными свойствами
ClientConfig config = new DefaultClientConfig(); config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( new HostnameVerifier() { @Override public boolean verify( String s, SSLSession sslSession ) { // whatever your matching policy states } } )); Client client = Client.create(config);
этот код будет выполняться только на тестовых серверах, поэтому я не хочу идти от добавления новых доверенных сертификатов каждый раз, когда мы создали новый тестовый сервер.
Это такой код, который в конечном итоге найдет свой путь в производстве (если не от вас, то кто-то другой, кто читает этот вопрос, скопирует и вставит небезопасные доверительные менеджеры, которые были предложены в их приложениях). Это так легко забыть удалить такой код, когда у вас есть крайний срок, так как он не появляется как проблема.
Если вы беспокоитесь о необходимости добавлять новые сертификаты каждый раз, когда у вас есть тестовый сервер, создайте свой собственный маленький ЦС, выдайте все сертификаты для тестовых серверов с помощью этого ЦС и импортируйте этот сертификат ЦС в хранилище доверия клиента. (Даже если вы не имеете дело с такими вещами, как отзыв сертификатов в локальной среде, это, безусловно, лучше, чем использование доверительного менеджера, который позволяет что-либо через.)
есть инструменты, которые помогут вам сделать это, например TinyCA или XCA.
поскольку я новичок в stackoverflow и имею меньшую репутацию, чтобы комментировать ответы других, я ставлю решение, предложенное Крисом Салиджем, с некоторой модификацией, которая работала для меня.
SSLContext ctx = null; TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){return null;} public void checkClientTrusted(X509Certificate[] certs, String authType){} public void checkServerTrusted(X509Certificate[] certs, String authType){} }}; try { ctx = SSLContext.getInstance("SSL"); ctx.init(null, trustAllCerts, null); } catch (NoSuchAlgorithmException | KeyManagementException e) { LOGGER.info("Error loading ssl context {}", e.getMessage()); } SSLContext.setDefault(ctx);
для всех на Джерси 2.x без лямбд, используйте это:
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; public static Client getUnsecureClient() throws Exception { SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); HostnameVerifier allowAll = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(allowAll).build(); }протестировано с Джерси-клиент 2.11 on JRE 1.7.
просто добавив тот же код с импортом. Также содержит нереализованный код, который необходим для компиляции. Сначала мне было трудно узнать, что было импортировано для этого кода. Также добавление правильного пакета для X509Certificate. Получил эту работу методом проб и ошибок:
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.security.cert.CertificateException; import javax.security.cert.X509Certificate; import javax.ws.rs.core.MultivaluedMap; TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { java.security.cert.X509Certificate[] chck = null; ; return chck; } public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // TODO Auto-generated method stub } public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public void checkClientTrusted( java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException { // TODO Auto-generated method stub } public void checkServerTrusted( java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException { // TODO Auto-generated method stub } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection .setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { ; }
Для Джерси 2.*:
Client client = ClientBuilder.newBuilder() .hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }).build();-> https://jersey.java.net/documentation/latest/migration.html
Для Джерси 1.X
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} public java.security.cert.X509Certificate[] getAcceptedIssuers() { // or you can return null too return new java.security.cert.X509Certificate[0]; } }}; SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String string, SSLSession sslSession) { return true; } });
Я заметил, что при использовании конфигурации http-клиента Apache с менеджером пула принятый ответ не работает.
В этом случае получается, что
ClientConfig.sslContextиClientConfig.hostnameVerifierсеттеры молча игнорируются. Поэтому, если вы используете пул соединений с конфигурацией http-клиента apache client, вы должны иметь возможность использовать следующий код для игнорирования проверки ssl:ClientConfig clientConfig = new ClientConfig(); // ... configure your clientConfig SSLContext sslContext = null; try { sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) { } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] {}; } } }, null); } catch (NoSuchAlgorithmException e) { //logger.debug("Ignoring 'NoSuchAlgorithmException' while ignoring ssl certificate validation."); } catch (KeyManagementException e) { //logger.debug("Ignoring 'KeyManagementException' while ignoring ssl certificate validation."); } Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", new SSLConnectionSocketFactory(sslContext, new AbstractVerifier() { @Override public void verify(String host, String[] cns, String[] subjectAlts) { } })) .build(); connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager); return ClientBuilder.newClient(clientConfig);
работал для меня с помощью этого кода. Может быть его для Java 1.7
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { // TODO Auto-generated method stub return null; } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // TODO Auto-generated method stub } @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // TODO Auto-generated method stub } }}; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { ; }
Comments