我有一个用Grizzly制作的REST服务器,它使用HTTPS并与Firefox完美配合.这是代码:
//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(); String 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 String[]{"/"}); //Set SSL webServer.setSSLConfig(ssl); //Start it up. System.out.println(String.format("Jersey app started with WADL available at " + "%sapplication.wadl\n", "https://localhost:9999/")); webServer.start();
现在,我尝试用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(String.class); }
得到:
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: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)
从我在网上找到的例子来看,似乎我需要设置一个Truststore然后设置某种TrustManager.这看起来像我的简单小项目的许多代码和设置工作.有没有更容易的方式来说..我相信这个证书并指向一个.cert文件?
当您说"有更简单的方法来...信任此证书"时,这正是您通过将证书添加到Java信任库而正在做的事情.这非常非常容易,而且您的客户端应用程序中无需任何操作即可识别或利用该信任存储.
在客户端计算机上,找到cacerts文件的位置(这是您的默认Java信任库,默认情况下位于
然后,键入以下内容:
keytool -import -alias-file -keystore
这会将证书导入您的信任存储区,然后,您的客户端应用程序将能够毫无问题地连接到您的Grizzly HTTPS服务器.
如果您不想将证书导入默认信任库 - 即,您只希望它可用于此一个客户端应用程序,而不是您在该计算机上的JVM上运行的任何其他内容 - 那么您可以为您的应用创建一个新的信任商店.而不是将keytool传递给现有的默认cacerts文件的路径,而是将keytool传递给新信任库文件的路径:
keytool -import -alias-file -keystore
系统将要求您设置并验证信任库文件的新密码.然后,当您启动客户端应用程序时,使用以下参数启动它:
java -Djavax.net.ssl.trustStore=-Djavax.net.ssl.trustStorePassword=
容易俗气,真的.
这是痛苦的路线:
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(String.class); } catch (Exception e) { e.printStackTrace(); }
一定要喜欢那六种不同的异常:).肯定有一些重构可以简化代码.但是,我喜欢虚拟机上的delfuego -D选项.我希望有一个我可以设置的javax.net.ssl.trustStore静态属性.只需两行代码即可完成.谁知道那会是哪里?
这可能要求太多,但理想情况下,不会使用keytool.相反,trustedStore将由代码动态创建,并在运行时添加cert.
必须有一个更好的答案.