2012-07-11 36 views
10

我是REST服務的新用戶。我需要使用由Jersey生成的RESTful API服務。問題出現是因爲該服務託管在遠程主機上,並且需要使用證書進行https訪問。通過https使用Java使用證書來使用RESTful服務

我從組織獲得了證書,並且能夠使用我的任何瀏覽器(在其上設置證書)訪問該REST API服務。

我看過很多帖子在這裏,而且我是按照這個話題的答案: Using HTTPS with REST in Java

現在,我已經在我的證書安裝在我的Java密鑰。但我不知道如何在我的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錯誤。

但後來我不知道如何使用密鑰庫上的證書進行SSL連接。 我一直還唸叨使用的SSLSocketFactory用於此目的,但我不能讓它工作作爲這篇文章解釋:How can I use different certificates on specific connections?

我已經成功地檢索密鑰庫我的證書與此代碼..現在我只是需要知道如何使用它連接:

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站點,但我仍然無法連接到需要發送證書進行身份驗證的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()); 

} 
} 
+1

您是如何生成密鑰庫的?在你發佈的代碼中,爲什麼使用'cacerts'信任庫?我建議將你的證書導入到它自己的JKS中,並在調用System.setProperty(「javax.net.ssl.keyStore」,「...」)時使用它。 – poida 2014-10-29 11:48:18

回答

2

假設你的服務器上部署這些代碼,你別的正確所做的一切(如同正確生成密鑰存儲核心,將其放置在它可以通過你的服務器可以訪問的位置,使用相同的Java版本你的代碼來生成密鑰庫),那麼我認爲你需要做的就是添加以下

<Connector SSLEnabled="true" clientAuth="false" keystoreFile="pathToKeystore" keystorePass="password" maxThreads="150" port="443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/> 

在你的服務器實例的server.xml中什麼在其上運行的客戶端和

<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/> 

IMP:如果您在此代碼旁邊使用Skype,請確保(取消選中)更改默認值,因爲它還使用相同的端口(80和443)進行其他連接

相關問題