Utilisation de HTTPS avec REST en Java

J’ai un serveur REST fabriqué dans Grizzly qui utilise HTTPS et fonctionne à merveille avec Firefox. Voici le code:

//Build a new Servlet Adapter. ServletAdapter adapter=new ServletAdapter(); adapter.addInitParameter("com.sun.jersey.config.property.packages", "My.services"); adapter.addInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, SecurityFilter.class.getName()); adapter.setContextPath("/"); adapter.setServletInstance(new ServletContainer()); //Configure SSL (See instructions at the top of this file on how these files are generated.) SSLConfig ssl=new SSLConfig(); Ssortingng keystoreFile=Main.class.getResource("resources/keystore_server.jks").toURI().getPath(); System.out.printf("Using keystore at: %s.",keystoreFile); ssl.setKeyStoreFile(keystoreFile); ssl.setKeyStorePass("asdfgh"); //Build the web server. GrizzlyWebServer webServer=new GrizzlyWebServer(getPort(9999),".",true); //Add the servlet. webServer.addGrizzlyAdapter(adapter, new Ssortingng[]{"/"}); //Set SSL webServer.setSSLConfig(ssl); //Start it up. System.out.println(Ssortingng.format("Jersey app started with WADL available at " + "%sapplication.wadl\n", "https://localhost:9999/")); webServer.start(); 

Maintenant, j’essaie de l’atteindre en Java:

 SSLContext ctx=null; try { ctx = SSLContext.getInstance("SSL"); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } ClientConfig config=new DefaultClientConfig(); config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null,ctx)); WebResource service=Client.create(new DefaultClientConfig()).resource("https://localhost:9999/"); //Attempt to view the user's page. try{ service .path("user/"+username) .get(Ssortingng.class); } 

Et obtenir:

 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 certificateion path to requested target at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:128) at com.sun.jersey.api.client.Client.handle(Client.java:453) at com.sun.jersey.api.client.WebResource.handle(WebResource.java:557) at com.sun.jersey.api.client.WebResource.get(WebResource.java:179) 

D’après les exemples que j’ai trouvés sur le Web, il semblerait que je devrais configurer un fichier Truststore, puis configurer une sorte de TrustManager. Cela ressemble à beaucoup de code et de travail d’installation pour mon petit projet simple. Y a-t-il un moyen plus simple de dire simplement … Je fais confiance à ce cert et pointez sur un fichier .cert?

Lorsque vous dites “y a-t-il un moyen plus simple de … faire confiance à ce cert”, c’est exactement ce que vous faites en ajoutant le cert à votre Java Trust Store. Et c’est très, très facile à faire, et il n’y a rien que vous ayez à faire dans votre application cliente pour que ce magasin soit reconnu ou utilisé.

Sur votre ordinateur client, recherchez l’emplacement de votre fichier cacerts (il s’agit de votre magasin de clés de confiance Java par défaut, situé par défaut sur / lib / security / certs / cacerts.

Ensuite, tapez ce qui suit:

 keytool -import -alias  -file  -keystore  

Cela permettra d’importer le certificate dans votre Trust Store et, ensuite, votre application client pourra se connecter sans problème à votre serveur Grizzly HTTPS.

Si vous ne souhaitez pas importer le certificate dans votre trust store par défaut (vous voulez simplement qu’il soit disponible pour cette application cliente, mais pas pour tout ce que vous exécutez sur votre JVM sur cette machine), vous pouvez alors: créer un nouveau magasin de confiance juste pour votre application. Au lieu de transmettre à keytool le chemin d’access au fichier cacerts par défaut existant, transmettez keytool le chemin d’access à votre nouveau fichier de magasin d’approbation:

 keytool -import -alias  -file  -keystore  

Vous serez invité à définir et à vérifier un nouveau mot de passe pour le fichier de magasin de clés de confiance. Ensuite, lorsque vous démarrez votre application client, démarrez-la avec les parameters suivants:

 java -Djavax.net.ssl.trustStore= -Djavax.net.ssl.trustStorePassword= 

Facile fromage, vraiment.

Voici l’itinéraire douloureux:

  SSLContext ctx = null; try { KeyStore trustStore; trustStore = KeyStore.getInstance("JKS"); trustStore.load(new FileInputStream("C:\\truststore_client"), "asdfgh".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory .getInstance("SunX509"); tmf.init(trustStore); ctx = SSLContext.getInstance("SSL"); ctx.init(null, tmf.getTrustManagers(), null); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } ClientConfig config = new DefaultClientConfig(); config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null, ctx)); WebResource service = Client.create(config).resource( "https://localhost:9999/"); service.addFilter(new HTTPBasicAuthFilter(username, password)); // Attempt to view the user's page. try { service.path("user/" + username).get(Ssortingng.class); } catch (Exception e) { e.printStackTrace(); } 

Je dois aimer ces six exceptions différentes capturées :). Il existe certainement des refactorisations pour simplifier un peu le code. Mais j’aime les options -D de delfuego sur la VM. Je souhaite qu’il y ait une propriété statique de javax.net.ssl.trustStore que je pourrais simplement définir. Juste deux lignes de code et fait. Quelqu’un sait où cela serait?

C’est peut-être trop demander, mais l’idéal serait que l’outil clé ne soit pas utilisé. Au lieu de cela, le TrustedStore serait créé dynamicment par le code et le certificate est ajouté à l’exécution.

Il doit y avoir une meilleure réponse.

Il ne faut pas oublier que cette erreur n’est pas uniquement due à des signatures auto-signées. Les nouveaux certificates Entrust CA échouent avec la même erreur, et la bonne chose à faire est de mettre à jour le serveur avec les certificates racine appropriés, et non de désactiver cette fonctionnalité de sécurité importante.

Découvrez ceci: http://code.google.com/p/resting/ . Je pourrais utiliser le repos pour consumr des services HTTPS REST.