Подтвердить что ты не робот

Игнорировать самоподписанный сертификат ssl с помощью Jersey Client

Я использую библиотеку клиента Джерси для запуска тестов против службы отдыха, работающей на jboss. У меня https настроен на сервере (работает на localhost), используя собственный сертификат.

Однако всякий раз, когда я запускаю свои тесты с помощью https url, я получаю следующую ошибку:

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.access$200(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);

Любая помощь будет принята с благодарностью.

4b9b3361

Ответ 1

После некоторого поиска и опрокидывания некоторых старых вопросов 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. * (проверено на 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();
}

Ответ 3

У меня была такая же проблема, и я не хотел, чтобы это было настроено глобально, поэтому я использовал тот же код 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);

Ответ 4

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

Это тот код, который в конечном итоге найдет свой путь в производстве (если не от вас, кто-то, кто читает этот вопрос, скопирует и вставляет незащищенные доверительные менеджеры, которые были предложены в их приложениях). Просто так легко забыть удалить этот тип кода, когда у вас есть крайний срок, поскольку он не отображается как проблема.

Если вы беспокоитесь о необходимости добавления новых сертификатов каждый раз, когда у вас есть тестовый сервер, создайте свой собственный ЦС, выпустите все сертификаты для тестовых серверов с помощью этого ЦС и импортируйте этот сертификат ЦС в хранилище доверия клиентов. (Даже если вы не имеете дело с такими вещами, как аннулирование онлайн-сертификата в локальной среде, это, безусловно, лучше, чем использование доверительного менеджера, который пропускает что-либо через.)

Есть инструменты, которые помогут вам сделать это, например TinyCA или XCA.

Ответ 5

Поскольку я новичок в 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);

Ответ 6

Для тех, кто на Джерси 2.x без lambdas, используйте это:

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

Протестировано jersey-client 2.11 на JRE 1.7.

Ответ 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) {
     ;
 }

Ответ 9

Для Джерси 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;
        }
    });

Ответ 10

Используйте лямбда для Джерси 2.x

  ClientBuilder.newBuilder()
            .hostnameVerifier((HostnameVerifier) (h, s) -> {
                return true;
            }).build();

Ответ 11

Я заметил, что при использовании конфигурации http-клиента Apache с диспетчером пула принятый ответ не работает.

В этом случае кажется, что ClientConfig.sslContext и ClientConfig.hostnameVerifier игнорируются. Поэтому, если вы используете пул соединений с конфигурацией HTTP-клиента Apache, вы можете использовать следующий код, чтобы игнорировать проверку 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);

Ответ 12

Хорошо, я хотел бы просто добавить свой класс только потому, что в будущем может появиться какой-то разработчик, который захочет подключиться к серверу Netbackup (или что-то подобное) и делать что-то из Java, игнорируя сертификат SSL. Это сработало для меня, и мы используем Windows Active Directory для аутентификации на сервере Netbackup.

public static void main(String[] args) throws Exception {
    SSLContext sslcontext = null;
    try {
        sslcontext = SSLContext.getInstance("TLS");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
        sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
            @Override
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }

            @Override
            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        }}, new java.security.SecureRandom());
    } catch (KeyManagementException ex) {
        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
    }
    //HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().credentials(username, password).build();
    ClientConfig clientConfig = new ClientConfig();
    //clientConfig.register(feature);
    Client client = ClientBuilder.newBuilder().withConfig(clientConfig)
            .sslContext(sslcontext)
            .hostnameVerifier((s1, s2) -> true)
            .build();

    //String the_url = "https://the_server:1556/netbackup/security/cacert";
    String the_token;
    {
        String the_url = "https://the_server:1556/netbackup/login";
        WebTarget webTarget = client.target(the_url);

        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
        String jsonString = new JSONObject()
                .put("domainType", "NT")
                .put("domainName", "XX")
                .put("userName", "the username")
                .put("password", "the password").toString();
        System.out.println(jsonString);
        Response response = invocationBuilder.post(Entity.json(jsonString));
        String data = response.readEntity(String.class);
        JSONObject jo = new JSONObject(data);
        the_token = jo.getString("token");
        System.out.println("token is:" + the_token);

    }
    {
        String the_url = "https://the_server:1556/netbackup/admin/jobs/1122012"; //job id 1122012 is an example
        WebTarget webTarget = client.target(the_url);
        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, the_token).header(HttpHeaders.ACCEPT, "application/vnd.netbackup+json;version=1.0");
        Response response = invocationBuilder.get();
        System.out.println("response status:" + response.getStatus());
        String data = response.readEntity(String.class);
        //JSONObject jo = new JSONObject(data);
        System.out.println(data);
    }
}

Я знаю, что это можно считать не по теме, но я уверен, что разработчик, который пытается подключиться к серверу Netbackup, вероятно, окажется здесь. Кстати большое спасибо всем ответам на этот вопрос! Спецификация, о которой я говорю, находится здесь, и в их примерах кода (в настоящее время) отсутствует пример Java.

*** Это, конечно, небезопасно, поскольку мы игнорируем сертификат!

Ответ 13

работал у меня с этим кодом. Может быть для 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) {
        ;
    }