2012-07-11 41 views
10

Tôi là người dùng mới đối với các dịch vụ REST. Tôi cần sử dụng một dịch vụ RESTful API được tạo ra với Jersey. Sự cố xảy ra do dịch vụ đó được lưu trữ trên máy chủ từ xa và nó yêu cầu quyền truy cập https bằng chứng chỉ.Sử dụng dịch vụ RESTful qua https với chứng chỉ bằng cách sử dụng Java

Tôi đã nhận được chứng chỉ của mình từ tổ chức và tôi có thể truy cập dịch vụ REST API đó với bất kỳ trình duyệt nào của tôi (có chứng chỉ được đặt trên chúng).

Tôi đã đọc rất nhiều bài viết trên đây, và tôi đã theo các câu trả lời về chủ đề này: Using HTTPS with REST in Java

Bây giờ tôi đã thiết lập giấy chứng nhận của tôi về Java Keystore tôi. Nhưng tôi không biết làm thế nào để sử dụng nó trên chương trình Java của tôi để nó sử dụng chính xác chứng chỉ tôi cần phải thực hiện kết nối https.

Đây là mã kết nối đơn giản của tôi cho các thử nghiệm cục bộ.

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

I'v đọc về việc sử dụng hệ thống thiết lập các thuộc tính để xác định đường dẫn đến keystore với mã này:

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

tôi vẫn nhận được 401 Lỗi kết nối đến máy chủ từ xa.

Nhưng sau đó tôi không biết cách tạo kết nối SSL bằng chứng chỉ của tôi trên kho khóa. Tôi cũng đã đọc về việc sử dụng sslSocketFactory cho mục đích này nhưng tôi không thể làm cho nó hoạt động như được giải thích trên bài đăng này: How can I use different certificates on specific connections?

Tôi đã lấy chứng chỉ từ kho khóa với mã này. cần phải biết cách sử dụng nó trong kết nối:

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

Ok đó là tập lệnh cuối cùng tôi đã viết. Tôi có thể kết nối với các trang web https nhưng tôi vẫn không thể kết nối với các trang web https yêu cầu gửi chứng chỉ của tôi để xác thực.

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

Bạn tạo kho khóa của mình như thế nào? Trong mã bạn đã đăng, tại sao lại sử dụng 'cacerts' truststore? Tôi sẽ đề nghị nhập chứng chỉ của bạn vào JKS của chính nó và sử dụng nó trong lời gọi đến 'System.setProperty (" javax.net.ssl.keyStore "," ... ")'. – poida

Trả lời

2

Giả sử rằng bạn đang triển khai mã này trên một máy chủ và bạn đã làm Mọi thứ khác một cách chính xác (Giống như tạo lõi keystore một cách chính xác và đặt nó ở một vị trí mà nó có thể được truy cập bởi máy chủ của bạn, sử dụng cùng một phiên bản java như mã của bạn để tạo ra các keystore) sau đó tôi nghĩ rằng những gì bạn cần làm là thêm sau

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

trong server.xml sơ thẩm server của bạn mà bạn đang chạy client và

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

IMP: Nếu bạn đang sử dụng Skype cùng với mã này, hãy đảm bảo (bỏ chọn) thay đổi giá trị mặc định vì nó cũng sử dụng cùng cổng (80 và 443) cho các kết nối bổ sung

Các vấn đề liên quan