【问题标题】:Accessing secure restful web services using jersey client使用 jersey 客户端访问安全的 RESTful Web 服务
【发布时间】:2011-03-26 22:43:04
【问题描述】:

我创建了基于 Jersey 的 Web 服务(通过 Netbeans 自动生成)。

我还创建了一个用户名“testClient”,密码为“secret”,创建了用户组“Users”,并使用 glassfish 3.0.1 管理控制台使用了文件 Realm。

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

我的网络服务已成功保护;当我访问该网站时,我会收到一个安全警告,然后提示我提供用户名和密码以访问该网站的任何内容。通过网络浏览器访问时它工作正常。

现在我已经编写了一个基于 jersey 的简单客户端,并尝试访问第一个项目提供的 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。我还尝试在同一台服务器上运行客户端和服务,但都是徒劳的。我被困住了;请帮助我。

干杯!

【问题讨论】:

    标签: security jersey client jdbcrealm


    【解决方案1】:

    我找到了一个关于我的问题的好资源。在这里

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 2015-12-08
      相关资源
      最近更新 更多