2010-08-08 6 views
10

저지 (Netbeans를 통해 자동 생성 됨)를 기반으로 웹 서비스를 만들었습니다.저지 클라이언트를 사용하여 안전하고 편안한 웹 서비스에 액세스

암호 "secret"로 사용자 이름 "testClient"를 만들고 사용자 그룹 "Users"를 만들었으며 glassfish 3.0.1 관리 콘솔을 사용하여 영역 Realm을 사용했습니다.

그에 따라 web.xml 및 sun-web.xml도 매핑했습니다.

웹 서비스가 안전하게 보호됩니다. 웹 사이트에 액세스 할 때 보안 경고가 표시되고 사용자 이름과 암호를 입력하여 웹 사이트의 모든 콘텐츠에 액세스 할 수 있습니다. 웹 브라우저를 통해 액세스 할 때 제대로 작동합니다.

이제 저지를 기반으로 한 간단한 클라이언트를 작성하고 1 차 프로젝트에서 제공하는 웹 서비스에 액세스하려고했습니다. 클라이언트 코드가 여기에있다

자동 생성 저지 클라이언트 코드

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

결과를 사용

나는 또한이 다른 서버에서 실행되는 두 개의 서로 다른 프로젝트가 모두 글래스 피쉬 3.0.1 것을 통보 할
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 

. 또한 같은 서버에서 클라이언트와 서비스를 실행하려고 시도했지만 모두 헛된 것입니다. 나는 붙어있다. 친절하게 도와주세요.

건배!

답변

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(); 
} 
관련 문제