it-swarm.com.de

Selbst signiertes SSL-Zertifikat mit Jersey Client ignorieren

Ich verwende die Jersey-Client-Bibliothek, um Tests mit einem auf jboss ausgeführten Restdienst auszuführen. __ Ich habe https auf dem Server (auf localhost ausgeführt) mit einem selbst signierten Zertifikat eingerichtet. 

Immer wenn ich meine Tests mit der https-URL durchführe, erhalte ich die folgende Fehlermeldung:

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

Ich weiß, dass dies daran liegt, dass mein selbstsigniertes cert nicht im Java-Keystore enthalten ist. Gibt es eine Möglichkeit, die Client die Gültigkeit des SSL-Zertifikats nicht überprüfen zu lassen und es trotzdem zu verwenden?

Dieser Code wird immer nur gegen Testserver ausgeführt, daher möchte ich nicht jedes Mal neue vertrauenswürdige Zertifikate hinzufügen, wenn wir einen neuen Testserver einrichten.

Hier ist der Code, der den Anruf tätigt:

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

Jede Hilfe wäre sehr dankbar.

59
Chris Salij

Nachdem ich einige alte Stackoverflow-Fragen durchsucht und durchforstet hatte, fand ich in einer zuvor gestellten SO - Frage eine Lösung:

Hier ist der Code, den ich am Ende verwendet habe.

// 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) {
    ;
}
83
Chris Salij

Für Jersey 2. * (getestet am 2.7) und 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();
}
50
eitan

Ich hatte das gleiche Problem und wollte nicht, dass dies global festgelegt wird. Daher habe ich denselben TrustManager- und SSLContext-Code wie oben verwendet

 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);
10
Ransom Briggs

Dieser Code wird immer nur auf Testservern ausgeführt, daher möchte ich nicht Sie müssen jedes Mal, wenn wir ein .__ einrichten, neue vertrauenswürdige Zertifikate hinzufügen. neuer Testserver.

Dies ist die Art von Code, die schließlich in der Produktion ihren Weg finden wird (wenn nicht von Ihnen, jemand, der diese Frage liest, wird die vorgeschlagenen unsicheren Vertrauensmanager kopieren und in ihre Anwendungen einfügen). Es ist so einfach zu vergessen, diese Art von Code zu entfernen, wenn Sie eine Frist haben, da dies kein Problem darstellt.

Wenn Sie befürchten, dass Sie jedes Mal, wenn Sie einen Testserver haben, neue Zertifikate hinzufügen müssen, erstellen Sie Ihre eigene kleine Zertifizierungsstelle, stellen Sie alle Zertifikate für die Testserver aus, die diese Zertifizierungsstelle verwenden, und importieren Sie dieses Zertifizierungsstellenzertifikat in Ihren Clientvertrauensspeicher. (Auch wenn Sie sich in einer lokalen Umgebung nicht mit der Sperrung von Online-Zertifikaten befassen, ist dies sicherlich besser als die Verwendung eines Vertrauensmanagers, der alles durchlässt.)

Es gibt Tools, die Ihnen dabei helfen, zum Beispiel TinyCA oder XCA .

8
Bruno

Da ich neu bei stackoverflow bin und weniger dafür bekannt bin, die Antworten anderer zu kommentieren, stelle ich die von Chris Salij vorgeschlagene Lösung mit einigen Modifikationen vor, die für mich gut funktionierten.

            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);
8
Mukesh

Für alle, die sich auf Jersey 2.x ohne Lambdas befinden:

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

Getestet mit Jersey-Client 2.11 am JRE 1.7 .

4
masi

Fügen Sie einfach den gleichen Code bei den Importen hinzu. Enthält auch den nicht implementierten Code, der zum Kompilieren benötigt wird. Ich hatte anfangs Probleme, herauszufinden, was für diesen Code importiert wurde. Hinzufügen des richtigen Pakets für das X509-Zertifikat. Habe das mit Versuch und Irrtum gearbeitet:

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) {
     ;
 }
3

Für Jersey 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
Marcelo C.

Für Jersey 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;
        }
    });
0
grep

Okay, ich möchte meine Klasse nur hinzufügen, weil es möglicherweise in Zukunft Entwickler gibt, die eine Verbindung zu einem Netbackup-Server (oder ähnlichem) herstellen und Java-Aufgaben ausführen möchten, während sie das SSL-Zertifikat ignorieren. Dies hat bei mir funktioniert und wir verwenden Windows Active Directory für die Authentifizierung des Netbackup-Servers.

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

Ich weiß, es kann als Off-Topic angesehen werden, aber ich wette, der Entwickler, der versucht, eine Verbindung zu einem Netbackup-Server herzustellen, wird wahrscheinlich hier landen. Übrigens vielen Dank an alle Antworten in dieser Frage! Die Spezifikation, über die ich spreche, ist hier und ihre Codebeispiele (derzeit) fehlt ein Java-Beispiel.

*** Das ist natürlich unsicher, da wir das Zertifikat ignorieren!

0
xtsoler

Ich habe festgestellt, dass die akzeptierte Antwort bei Verwendung der Apache-HTTP-Client-Konfiguration mit einem Pooling-Manager nicht funktioniert.

In diesem Fall scheinen die Setzer ClientConfig.sslContext und ClientConfig.hostnameVerifier still zu ignorieren. Wenn Sie also mit der HTTP-Client-Konfiguration des Apache-Clients Verbindungspooling verwenden, sollten Sie den folgenden Code verwenden können, um die SSL-Überprüfung zu ignorieren:

  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);
0