使用Java通过https和REST使用RESTful服务

我是REST服务的新用户。 我需要使用Jersey生成的RESTful API服务。 问题出现是因为该服务托管在远程主机上,并且需要https访问证书。

我从组织获得了我的证书,并且我能够使用我的任何浏览器访问该REST API服务(其上设置了证书)。

我在这里阅读了很多post,我已经按照这个主题的答案: 在Java中使用HTTPS和REST

现在我在我的Java Keystore上设置了证书。 但我不知道如何在我的Java程序中使用它,所以它使用我需要的证书来进行https连接。

这是我用于本地测试的简单连接代码。

package rest.test.first; import java.net.URI; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriBuilder; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; public class TestClient{ public static void main(String[]args){ ClientConfig config= new DefaultClientConfig(); Client client=Client.create(config); WebResource service=client.resource(getBaseURI()); //Fluentinterfaces System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(ClientResponse.class).toString()); //Getplaintext System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(String.class)); //GetXML System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_XML).get(String.class)); //TheHTML System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_HTML).get(String.class)); } private static URI getBaseURI(){ return UriBuilder.fromUri("http://localhost:8080/rest.test").build(); } } 

我读到了使用系统集属性来指定密钥库的路径,使用以下代码:

 System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "password"); 

我仍然在连接到远程服务器时遇到401错误。

但后来我不知道如何使用我在keystore上的证书进行SSL连接。 我也一直在阅读有关使用sslSocketFactory的信息,但是我无法按照这篇文章中的说明工作: 如何在特定连接上使用不同的证书?

我已经设法使用此代码从密钥库中检索我的证书..现在我只需要知道如何在连接中使用它:

 package rest.test.first; import java.io.FileInputStream; import java.security.KeyStore; import java.security.cert.Certificate; public class keystore { public static void main(String[] args) throws Exception { String keystoreFilename = "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"; char[] password = "changeit".toCharArray(); String alias = "remote_https_server"; FileInputStream fIn = new FileInputStream(keystoreFilename); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(fIn, password); Certificate cert = keystore.getCertificate(alias); System.out.println(cert); } } 

好的,这是我写的最后一个脚本。 我可以连接到https站点,但我仍然无法连接到需要发送我的证书进行身份validation的https站点。

 package rest.test.first; import java.io.*; import java.net.*; import java.security.*; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; public class urlConnection{ public static void main(String args[]) throws Exception { System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); //TrustStore.. char[] passphrase = "changeit".toCharArray(); //password KeyStore keystore = KeyStore.getInstance("JKS"); //KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(new FileInputStream("/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"), passphrase); //path //TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //instance TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keystore); SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManagers = tmf.getTrustManagers(); context.init(null, trustManagers, null); SSLSocketFactory sf = context.getSocketFactory(); URL url = new URL("https://www.google.es"); HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection(); httpsCon.setSSLSocketFactory(sf); httpsCon.setRequestMethod("GET"); /*InputStream inStrm = httpsCon.getInputStream(); System.out.println("\nContent at " + url); int ch; while (((ch = inStrm.read()) != -1)){ System.out.print((char) ch); inStrm.close(); }*/ System.out.println("Response Message is " + httpsCon.getResponseMessage()); } } 

假设您正在服务器上部署此代码并且您已正确完成所有其他操作(例如正确生成密钥库核心并将其放置在服务器可以访问的位置,使用与您的代码相同的Java版本来生成密钥库)那么我认为你需要做的是添加以下内容

  

在运行客户端的Server实例的server.xml中

  

IMP:如果您在此代码旁边使用Skype,请务必(取消选中)更改默认值,因为它还使用相同的端口(80和443)进行其他连接