2012-07-11 10 views
10

私はRESTサービスの新しいユーザーです。 Jerseyで生成されたRESTful APIサービスを使用する必要があります。この問題は、そのサービスがリモートホスト上でホストされ、証明書付きのhttpsアクセスが必要なために発生します。Javaを使用してcertficateでhttpsで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(); 
} 
} 

I'vは、このコードをキーストアへのパスを指定するには、システム設定のプロパティを使用して読ん:

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?

私はこのコードをキーストアからの私の証明書を取得するために管理してきました...ちょうど今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); 
     } 
    } 

これは私が書いた最後のスクリプトです。私は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

答えて

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"/> 
あなたがクライアントを実行して

<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/> 
されているサーバーインスタンスのserver.xmlの

以下を追加しています

IMP:このコードと一緒にSkypeを使用している場合、追加の接続に同じポート(80と443)を使用するので、デフォルト値を変更してください(チェックを外す)

関連する問題