2010-08-08 55 views
10

我已經基於澤西島(通過Netbeans自動生成)創建了Web服務。使用澤西島客戶端訪問安全寧靜的Web服務

我還創建了一個用戶名「testClient」,其密碼爲「secret」,並創建了用戶組「Users」,並使用了glassfish 3.0.1管理控制檯的Realm文件。

我也相應地映射了web.xml和sun-web.xml。

我的網絡服務已成功安全保護;當我訪問網站時,我收到安全警告,然後提示用戶名和密碼訪問網站的任何內容。通過網絡瀏覽器訪問時,它工作正常。

現在我寫了一個基於澤西島的簡單客戶端,並試圖訪問第一個項目提供的Web服務;客戶端代碼是在這裏

自動生成Jersey客戶端代碼

public class JerseyClient { 
    private WebResource webResource; 
    private Client client; 
    private static final String BASE_URI = "https://localhost:9028/testsecurity2/resources"; 

    public JerseyClient() { 
     com.sun.jersey.api.client.config.ClientConfig config = new com.sun.jersey.api.client.config.DefaultClientConfig(); // SSL configuration 
     // SSL configuration 
     config.getProperties().put(com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new com.sun.jersey.client.urlconnection.HTTPSProperties(getHostnameVerifier(), getSSLContext())); 
     client = Client.create(config); 
     webResource = client.resource(BASE_URI).path("manufacturers"); 
    } 

    public <T> T get_XML(Class<T> responseType) throws UniformInterfaceException { 
     return webResource.accept(javax.ws.rs.core.MediaType.APPLICATION_XML).get(responseType); 
    } 

    public <T> T get_JSON(Class<T> responseType) throws UniformInterfaceException { 
     return webResource.accept(javax.ws.rs.core.MediaType.APPLICATION_JSON).get(responseType); 
    } 

    public void close() { 
     client.destroy(); 
    } 

    public void setUsernamePassword(String username, String password) { 
     client.addFilter(new com.sun.jersey.api.client.filter.HTTPBasicAuthFilter(username, password)); 
    } 

    private HostnameVerifier getHostnameVerifier() { 
     return new HostnameVerifier() { 

      @Override 
      public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { 
       return true; 
      } 
     }; 
    } 

    private SSLContext getSSLContext() { 
     javax.net.ssl.TrustManager x509 = new javax.net.ssl.X509TrustManager() { 

      @Override 
      public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException { 
       return; 
      } 

      @Override 
      public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException { 
       return; 
      } 

      @Override 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
       return null; 
      } 
     }; 
     SSLContext ctx = null; 
     try { 
      ctx = SSLContext.getInstance("SSL"); 
      ctx.init(null, new javax.net.ssl.TrustManager[]{x509}, null); 
     } catch (java.security.GeneralSecurityException ex) { 
     } 
     return ctx; 
    } 

} 

守則主要方法;使用自動生成的代碼

JerseyClient client = new JerseyClient(); 
client.setUsernamePassword("testClient", "secret"); 
Object response = client.get_XML(String.class); 
// do whatever with response 
client.close(); 

結果:

Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
     at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:128) 
     at com.sun.jersey.api.client.filter.HTTPBasicAuthFilter.handle(HTTPBasicAuthFilter.java:78) 
     at com.sun.jersey.api.client.Client.handle(Client.java:457) 
     at com.sun.jersey.api.client.WebResource.handle(WebResource.java:557) 
     at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:69) 
     at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:451) 
     at clients.JerseyClient.get_XML(JerseyClient.java:23) 
     at clients.NewMain1.main(NewMain1.java:20) 
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:808) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1139) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123) 
     at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 
     at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049) 
     at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:373) 
     at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318) 
     at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:215) 
     at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:126) 
     ... 7 more 
Caused by: java.io.EOFException: SSL peer shut down incorrectly 
     at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:333) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:789) 
     ... 17 more 
Java Result: 1 

我也想告知,這些都是在不同的服務器上運行兩個不同的項目都是GlassFish的3.0.1。我也嘗試在同一臺服務器上運行客戶端和服務,但都徒勞無功。我卡住了;請幫助我。

乾杯!

回答

16

我發現了一個關於我的問題的好資源。這是

http://wiki.open-esb.java.net/attach/RestBCEchoSSL/SslClient.java

我改變了我的代碼對於給定的源一些改變它完美地工作。其實我沒有正確地通過證書和密鑰存儲。

這裏是完整的代碼。

package clients; 

import com.sun.jersey.api.client.*; 
import javax.net.ssl.*; 
import java.io.*; 
import java.net.Socket; 
import java.security.*; 
import javax.ws.rs.core.UriBuilder; 
import com.sun.jersey.client.urlconnection.HTTPSProperties; 

public class JerseyClient { 

    private WebResource webResource; 
    private Client client; 
    //private static final String BASE_URI = "https://localhost:9028/testsecurity2/resources"; 
    private static final String truststore_path = "D:/Practice Apps/glassfish-3.0.1 Stand Alone/glassfish/domains/domain2/config/cacerts.jks"; 
    private static final String truststore_password = "changeit"; 
    private static final String keystore_path = "D:/Practice Apps/glassfish-3.0.1 Stand Alone/glassfish/domains/domain2/config/keystore.jks"; 
    private static final String keystore_password = "changeit"; 
    private static final String url = "https://localhost:9029/testsecurity2/resources/manufacturers/"; 

    public JerseyClient() { 
     com.sun.jersey.api.client.config.ClientConfig config = new com.sun.jersey.api.client.config.DefaultClientConfig(); // SSL configuration 
     // SSL configuration 
     config.getProperties().put(com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new com.sun.jersey.client.urlconnection.HTTPSProperties(getHostnameVerifier(), getSSLContext())); 
     client = Client.create(config); 
     webResource = client.resource(url); 
    } 

    public <T> T get_XML(Class<T> responseType) throws UniformInterfaceException { 
     return webResource.accept(javax.ws.rs.core.MediaType.APPLICATION_XML).get(responseType); 
    } 

    public <T> T get_JSON(Class<T> responseType) throws UniformInterfaceException { 
     return webResource.accept(javax.ws.rs.core.MediaType.APPLICATION_JSON).get(responseType); 
    } 

    public void close() { 
     client.destroy(); 
    } 

    public void setUsernamePassword(String username, String password) { 
     client.addFilter(new com.sun.jersey.api.client.filter.HTTPBasicAuthFilter(username, password)); 
    } 

    private HostnameVerifier getHostnameVerifier() { 
     return new HostnameVerifier() { 

      @Override 
      public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { 
       return true; 
      } 
     }; 
    } 

    private SSLContext getSSLContext() { 

     TrustManager mytm[] = null; 
     KeyManager mykm[] = null; 

     try { 
      mytm = new TrustManager[]{new MyX509TrustManager(truststore_path, truststore_password.toCharArray())}; 
      mykm = new KeyManager[]{new MyX509KeyManager(keystore_path, keystore_password.toCharArray())}; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 

     SSLContext ctx = null; 
     try { 
      ctx = SSLContext.getInstance("SSL"); 
      ctx.init(mykm, mytm, null); 
     } catch (java.security.GeneralSecurityException ex) { 
     } 
     return ctx; 
    } 

    /** 
    * Taken from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html 
    * 
    */ 
    static class MyX509TrustManager implements X509TrustManager { 

     /* 
     * The default PKIX X509TrustManager9. We'll delegate 
     * decisions to it, and fall back to the logic in this class if the 
     * default X509TrustManager doesn't trust it. 
     */ 
     X509TrustManager pkixTrustManager; 

     MyX509TrustManager(String trustStore, char[] password) throws Exception { 
      this(new File(trustStore), password); 
     } 

     MyX509TrustManager(File trustStore, char[] password) throws Exception { 
      // create a "default" JSSE X509TrustManager. 

      KeyStore ks = KeyStore.getInstance("JKS"); 

      ks.load(new FileInputStream(trustStore), password); 

      TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); 
      tmf.init(ks); 

      TrustManager tms[] = tmf.getTrustManagers(); 

      /* 
      * Iterate over the returned trustmanagers, look 
      * for an instance of X509TrustManager. If found, 
      * use that as our "default" trust manager. 
      */ 
      for (int i = 0; i < tms.length; i++) { 
       if (tms[i] instanceof X509TrustManager) { 
        pkixTrustManager = (X509TrustManager) tms[i]; 
        return; 
       } 
      } 

      /* 
      * Find some other way to initialize, or else we have to fail the 
      * constructor. 
      */ 
      throw new Exception("Couldn't initialize"); 
     } 

     /* 
     * Delegate to the default trust manager. 
     */ 
     public void checkClientTrusted(X509Certificate[] chain, String authType) 
       throws CertificateException { 
      try { 
       pkixTrustManager.checkClientTrusted(chain, authType); 
      } catch (CertificateException excep) { 
       // do any special handling here, or rethrow exception. 
      } 
     } 

     /* 
     * Delegate to the default trust manager. 
     */ 
     public void checkServerTrusted(X509Certificate[] chain, String authType) 
       throws CertificateException { 
      try { 
       pkixTrustManager.checkServerTrusted(chain, authType); 
      } catch (CertificateException excep) { 
       /* 
       * Possibly pop up a dialog box asking whether to trust the 
       * cert chain. 
       */ 
      } 
     } 

     /* 
     * Merely pass this through. 
     */ 
     public X509Certificate[] getAcceptedIssuers() { 
      return pkixTrustManager.getAcceptedIssuers(); 
     } 
    } 

    /** 
    * Inspired from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html 
    * 
    */ 
    static class MyX509KeyManager implements X509KeyManager { 

     /* 
     * The default PKIX X509KeyManager. We'll delegate 
     * decisions to it, and fall back to the logic in this class if the 
     * default X509KeyManager doesn't trust it. 
     */ 
     X509KeyManager pkixKeyManager; 

     MyX509KeyManager(String keyStore, char[] password) throws Exception { 
      this(new File(keyStore), password); 
     } 

     MyX509KeyManager(File keyStore, char[] password) throws Exception { 
      // create a "default" JSSE X509KeyManager. 

      KeyStore ks = KeyStore.getInstance("JKS"); 
      ks.load(new FileInputStream(keyStore), password); 

      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE"); 
      kmf.init(ks, password); 

      KeyManager kms[] = kmf.getKeyManagers(); 

      /* 
      * Iterate over the returned keymanagers, look 
      * for an instance of X509KeyManager. If found, 
      * use that as our "default" key manager. 
      */ 
      for (int i = 0; i < kms.length; i++) { 
       if (kms[i] instanceof X509KeyManager) { 
        pkixKeyManager = (X509KeyManager) kms[i]; 
        return; 
       } 
      } 

      /* 
      * Find some other way to initialize, or else we have to fail the 
      * constructor. 
      */ 
      throw new Exception("Couldn't initialize"); 
     } 

     public PrivateKey getPrivateKey(String arg0) { 
      return pkixKeyManager.getPrivateKey(arg0); 
     } 

     public X509Certificate[] getCertificateChain(String arg0) { 
      return pkixKeyManager.getCertificateChain(arg0); 
     } 

     public String[] getClientAliases(String arg0, Principal[] arg1) { 
      return pkixKeyManager.getClientAliases(arg0, arg1); 
     } 

     public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) { 
      return pkixKeyManager.chooseClientAlias(arg0, arg1, arg2); 
     } 

     public String[] getServerAliases(String arg0, Principal[] arg1) { 
      return pkixKeyManager.getServerAliases(arg0, arg1); 
     } 

     public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) { 
      return pkixKeyManager.chooseServerAlias(arg0, arg1, arg2); 
     } 
    } 
} 

和代碼在主類運行客戶端

public static void main(String[] args) { 

    JerseyClient client = new JerseyClient(); 
    client.setUsernamePassword("testClient", "secret"); 
    Object response = client.get_XML(String.class); 
    System.out.println(response); 
    // do whatever with response 
    client.close(); 
} 
相關問題