代码之家  ›  专栏  ›  技术社区  ›  caub Zirak

连接到安全的websocket

  •  8
  • caub Zirak  · 技术社区  · 11 年前

    我正在尝试使用Jetty(或任何其他库)连接到安全的websocket。

    问题是我收到“找不到可信证书”错误。我使用的是使用keytool生成的自签名证书。可以做什么?

    import java.net.URI;
    import java.util.concurrent.Future;
    
    import org.eclipse.jetty.util.resource.Resource;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.eclipse.jetty.websocket.api.Session;
    import org.eclipse.jetty.websocket.api.WebSocketAdapter;
    import org.eclipse.jetty.websocket.client.WebSocketClient;
    
    public class Socket extends WebSocketAdapter{
    
        public static void main(String[] args) {
            String url = "wss://qa.sockets.stackexchange.com/"; //or "wss://echo.websocket.org"
            // making sure the the jvm find keystore
            String JAVASEC="C:/Program Files/Java/jdk1.8.0_25/jre/lib/security/";
            System.setProperty("javax.net.ssl.keyStore", JAVASEC+"keystore.jks");
            System.setProperty("javax.net.ssl.trustStore", JAVASEC+"cacerts.jks");
            System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
    
            System.out.println(System.getProperty("javax.net.ssl.trustStore"));
            SslContextFactory sslContextFactory = new SslContextFactory();
            Resource keyStoreResource = Resource.newResource(Socket.class.getResource("/keystore.jks"));//generated with keytool
            sslContextFactory.setKeyStoreResource(keyStoreResource);
            sslContextFactory.setKeyStorePassword("password");
            sslContextFactory.setKeyManagerPassword("password");
            WebSocketClient client = new WebSocketClient(sslContextFactory);
            try{
                client.start();
                Socket socket = new Socket();
                Future<Session> fut = client.connect(socket,URI.create(url));
                Session session = fut.get();
                session.getRemote().sendString("Hello");
            }
            catch (Throwable t){
                t.printStackTrace(System.err);
            }
        }
    
    
        @Override
        public void onWebSocketConnect(Session sess){
            super.onWebSocketConnect(sess);
            System.out.println("Socket Connected: " + sess);
        }
    
        @Override
        public void onWebSocketText(String message){
            super.onWebSocketText(message);
            System.out.println("Received TEXT message: " + message);
        }
    
        @Override
        public void onWebSocketClose(int statusCode, String reason){
            super.onWebSocketClose(statusCode,reason);
            System.out.println("Socket Closed: [" + statusCode + "] " + reason);
        }
    
        @Override
        public void onWebSocketError(Throwable cause){
            super.onWebSocketError(cause);
            cause.printStackTrace(System.err);
        }
    }
    

    这是一个使用Tyrus websocket客户端的尝试,我没有收到SSL错误,但它没有打印任何内容:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URI;
    import java.net.URISyntaxException;
    
    import javax.websocket.ClientEndpointConfig;
    import javax.websocket.CloseReason;
    import javax.websocket.DeploymentException;
    import javax.websocket.Endpoint;
    import javax.websocket.EndpointConfig;
    import javax.websocket.MessageHandler;
    import javax.websocket.Session;
    
    import org.glassfish.grizzly.ssl.SSLContextConfigurator;
    import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
    import org.glassfish.tyrus.client.ClientManager;
    import org.glassfish.tyrus.container.grizzly.GrizzlyEngine;
    
    public class ClientWebSocketEndpoint extends Endpoint {
    
        public static void main(String[] a) throws IOException{
    
            ClientManager client = ClientManager.createClient();
    
            //System.getProperties().put("javax.net.debug", "all");
            final SSLContextConfigurator defaultConfig = new SSLContextConfigurator();
    
            defaultConfig.retrieve(System.getProperties());
                // or setup SSLContextConfigurator using its API.
    
            SSLEngineConfigurator sslEngineConfigurator =
                new SSLEngineConfigurator(defaultConfig, true, false, false);
            client.getProperties().put(GrizzlyEngine.SSL_ENGINE_CONFIGURATOR,
                sslEngineConfigurator);
            Session session = null;
            final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
    
            try {
                session = client.connectToServer(ClientWebSocketEndpoint.class, cec, new URI("wss://qa.sockets.stackexchange.com/"));// or "wss://echo.websocket.org"
    
            } catch (DeploymentException | URISyntaxException e) {
                e.printStackTrace();
            } finally {
                if (session != null && session.isOpen())
                    session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Bye"));
    
            }
    
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            br.readLine();
        }
    
        @Override
        public void onOpen(Session session, EndpointConfig config) {
            session.addMessageHandler(new MessageHandler.Whole<String>() {
    
                @Override
                public void onMessage(String message) {
                    System.out.println("Received message: "+message);
                }
            });
            try {
                session.getBasicRemote().sendText("1-questions-active");
                session.getBasicRemote().sendText("155-questions-active");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    }
    

    相比之下,JS/node中的这段简单代码可以工作

    var WebSocket = require('ws')
      , ws = new WebSocket('wss://qa.sockets.stackexchange.com/');//"wss://echo.websocket.org"
    
    ws.on('message', function(message) {
        console.log('received: %s', message);
    });
    ws.on('open', function() {
        ws.send('155-questions-active');
        ws.send('1-questions-active');
    });
    

    我很高兴知道一个在Java中工作的websocket客户端

    3 回复  |  直到 11 年前
        1
  •  14
  •   Joakim Erdfelt    5 年前

    正确的方法是将客户端密钥库/信任库配置为信任特定的自签名服务器证书。stackoverflow上有很多答案,演示了如何通过适当配置密钥库和/或信任库文件内容来使用Java实现这一点。(无需代码)。

    如果您想“只连接”,并且不关心信任、证书有效性,甚至不关心端点标识验证(基本上是构成一个安全连接的所有好东西),那么您就不需要处理密钥库、信任库或自定义 X509TrustManagers 甚至定制 SSLContexts 以连接到服务。这种需求在开发/测试/qa期间很常见,但不应在生产代码中使用。

    使用Jetty 9.4.35.v20201120时,只需配置 SslContextFactory.Client (属于 HttpClient 哪一个 WebSocketClient 正在使用)信任所有证书。

    import java.net.URI;
    import java.util.concurrent.Future;
    
    import org.eclipse.jetty.client.HttpClient;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.eclipse.jetty.websocket.api.Session;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
    import org.eclipse.jetty.websocket.api.annotations.WebSocket;
    import org.eclipse.jetty.websocket.client.WebSocketClient;
    
    @WebSocket
    public class SecureClientSocket
    {
        private static final Logger LOG = Log.getLogger(SecureClientSocket.class);
    
        public static void main(String[] args)
        {
            String url = "wss://qa.sockets.stackexchange.com/";
    
            SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
            // Tell sslContextFactory to trust all server certificates
            // This is suitable for test/qa environments, and internal environments,
            // but IS NOT SUITABLE FOR PRODUCTION.
            // Note: this is not actually necessary for wss://qa.sockets.stackexchange.com/
            sslContextFactory.setTrustAll(true);
            // If you do choose to comment out the above, this option will cause the
            // Java client side SSL/TLS to validate the server certificate name
            // against the URL used to connect to the server, if it doesn't match
            // then the connection is not established.
            sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS");
    
            HttpClient httpClient = new HttpClient(sslContextFactory);
            try
            {
                httpClient.start();
                WebSocketClient client = new WebSocketClient(httpClient);
                client.start();
                SecureClientSocket socket = new SecureClientSocket();
                Future<Session> fut = client.connect(socket, URI.create(url));
                Session session = fut.get();
                session.getRemote().sendString("Hello");
                session.getRemote().sendString("155-questions-active");
            }
            catch (Throwable t)
            {
                LOG.warn(t);
            }
        }
    
        @OnWebSocketConnect
        public void onConnect(Session sess)
        {
            LOG.info("onConnect({})", sess);
        }
    
        @OnWebSocketClose
        public void onClose(int statusCode, String reason)
        {
            LOG.info("onClose({}, {})", statusCode, reason);
        }
    
        @OnWebSocketError
        public void onError(Throwable cause)
        {
            LOG.warn(cause);
        }
    
        @OnWebSocketMessage
        public void onMessage(String msg)
        {
            LOG.info("onMessage() - {}", msg);
        }
    }
    

    结果会是这样的。。。

    2020-12-21 14:03:28.228:INFO::main: Logging initialized @173ms to org.eclipse.jetty.util.log.StdErrLog
    2020-12-21 14:03:28.401:WARN:oejusS.config:main: Trusting all certificates configured for Client@4b5a5ed1[provider=null,keyStore=null,trustStore=null]
    2020-12-21 14:03:28.402:WARN:oejusS.config:main: No Client EndPointIdentificationAlgorithm configured for Client@4b5a5ed1[provider=null,keyStore=null,trustStore=null]
    2020-12-21 14:03:28.862:INFO:j.SecureClientSocket:HttpClient@3712b94-60: onConnect(WebSocketSession[websocket=JettyAnnotatedEventDriver[jetty.SecureClientSocket@3f38289c],behavior=CLIENT,connection=WebSocketClientConnection@7556df66::DecryptedEndPoint@11c4a450{l=/192.168.1.217:46512,r=qa.sockets.stackexchange.com/198.252.206.25:443,OPEN,fill=-,flush=-,to=66/300000},remote=WebSocketRemoteEndpoint@278a12bf[batching=true],incoming=JettyAnnotatedEventDriver[jetty.SecureClientSocket@3f38289c],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]])
    2020-12-21 14:03:30.648:INFO:j.SecureClientSocket:HttpClient@3712b94-62: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"graphicdesign.stackexchange.com\",\"id\":138914,\"titleEncodedFancy\":\"How to achieve purple, paper background texture look?\",\"bodySummary\":\"How is the below purple background texture look achieved? I'm assuming it is a paper texture effect with different layers of light? However when I try to apply both the effect it never turns out the ...\",\"tags\":[\"texture\"],\"lastActivityDate\":1608581010,\"url\":\"https://graphicdesign.stackexchange.com/questions/138914/how-to-achieve-purple-paper-background-texture-look\",\"ownerUrl\":\"https://graphicdesign.stackexchange.com/users/155152/homan-cheung\",\"ownerDisplayName\":\"Homan Cheung\",\"apiSiteParameter\":\"graphicdesign\"}"}
    2020-12-21 14:03:30.791:INFO:j.SecureClientSocket:HttpClient@3712b94-60: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"unix.stackexchange.com\",\"id\":457386,\"titleEncodedFancy\":\"IPtables logging is not working in CentOS 7\",\"bodySummary\":\"I want to log all the traffic which comes in and out from the port X. I have followed below steps.\\r\\nEdited /etc/syslog.conf , /etc/rsyslog.conf , /etc/systemd/system/rsyslog.service.d/rsyslog.conf ...\",\"tags\":[\"centos\",\"kernel\",\"iptables\",\"logs\"],\"lastActivityDate\":1608581010,\"url\":\"https://unix.stackexchange.com/questions/457386/iptables-logging-is-not-working-in-centos-7\",\"ownerUrl\":\"https://unix.stackexchange.com/users/301499/karthikeyan-s\",\"ownerDisplayName\":\"Karthikeyan s\",\"apiSiteParameter\":\"unix\"}"}
    2020-12-21 14:03:32.235:INFO:j.SecureClientSocket:HttpClient@3712b94-62: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"math.stackexchange.com\",\"id\":812563,\"titleEncodedFancy\":\"Jacobian of exponential mapping in SO3/SE3\",\"bodySummary\":\"Following this post\\nJacobian matrix of the Rodrigues&#39; formula (exponential map)\\n\\nWhat if I really need the Jacobian of the exponential mapping function in $\\\\omega \\\\neq 0$?\\n\\nBasically, I want to ...\",\"tags\":[\"lie-groups\",\"3d\",\"rotations\",\"numerical-optimization\",\"rigid-transformation\"],\"lastActivityDate\":1608581012,\"url\":\"https://math.stackexchange.com/questions/812563/jacobian-of-exponential-mapping-in-so3-se3\",\"ownerUrl\":\"https://math.stackexchange.com/users/153816/user153816\",\"ownerDisplayName\":\"user153816\",\"apiSiteParameter\":\"math\"}"}
    2020-12-21 14:03:35.343:INFO:j.SecureClientSocket:HttpClient@3712b94-60: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"raspberrypi.stackexchange.com\",\"id\":76325,\"titleEncodedFancy\":\"GCC version for compiling a loadable kernel module\",\"bodySummary\":\"I am not very familiar with Linux, so may be my question is a little bit foolish.\\n\\nI would like to compile kernel module without recompiling the kernel (USB Wi-Fi stick driver for MT7106U chip). I ...\",\"tags\":[\"kernel\",\"modules\",\"gcc\"],\"lastActivityDate\":1608581015,\"url\":\"https://raspberrypi.stackexchange.com/questions/76325/gcc-version-for-compiling-a-loadable-kernel-module\",\"ownerUrl\":\"https://raspberrypi.stackexchange.com/users/77643/cyclone125\",\"ownerDisplayName\":\"cyclone125\",\"apiSiteParameter\":\"raspberrypi\"}"}
    2020-12-21 14:03:36.775:INFO:j.SecureClientSocket:JettyShutdownThread: onClose(1006, Disconnected)
    
        2
  •  4
  •   kucing_terbang    11 年前

    嗯,我尝试使用您的代码来复制问题,但没有效果(获取证书,使用keytool命令导入它,然后运行代码)。我的输出是这样的。

    2015-03-22 23:03:16.192:INFO::main: Logging initialized @503ms
    Socket Connected:WebSocketSession[websocket=JettyListenerEventDriver[com.ivan.Main],behavior=CLIENT,connection=WebSocketClientConnection@77ae29b0{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],p=Parser@4e086d6d[ExtensionStack,s=START,c=0,len=0,f=null,p=WebSocketPolicy@7c0ceccc[behavior=CLIENT,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},remote=WebSocketRemoteEndpoint@49f64[batching=true],incoming=JettyListenerEventDriver[com.ivan.Main],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]]
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"cogsci.stackexchange.com\",\"id\":9404,\"titleEncodedFancy\":\"What&#39;s the difference between repetition suppression and habituation?\",\"bodySummary\":\"Neural repetition suppression seems to be describing behavioral habituation on a neuronal level. What's the difference between these two terms?\\n\",\"tags\":[\"cognitive-neuroscience\",\"terminology\",\"conditioning\",\"perceptual-learning\"],\"lastActivityDate\":1427036607,\"url\":\"http://cogsci.stackexchange.com/questions/9404/whats-the-difference-between-repetition-suppression-and-habituation\",\"ownerUrl\":\"http://cogsci.stackexchange.com/users/7569/recursive-farts\",\"ownerDisplayName\":\"RECURSIVE FARTS\",\"apiSiteParameter\":\"cogsci\"}"}
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"mathematica.stackexchange.com\",\"id\":77933,\"titleEncodedFancy\":\"FunctionDomain doesn&#39;t work with If\",\"bodySummary\":\"When I call FunctionDomain for function defined by formule with If, for example \\n\\nf[x_]:=If[x&lt;0, x, x^3], \\n\\nI get \\\"Unable to find the domain with the available methods\\\". What should I do to get a ...\",\"tags\":[\"functions\"],\"lastActivityDate\":1427036609,\"url\":\"http://mathematica.stackexchange.com/questions/77933/functiondomain-doesnt-work-with-if\",\"ownerUrl\":\"http://mathematica.stackexchange.com/users/27150/adolzi\",\"ownerDisplayName\":\"adolzi\",\"apiSiteParameter\":\"mathematica\"}"}
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"serverfault.com\",\"id\":677390,\"titleEncodedFancy\":\"Smart Array E200i battery on 350ML did not fix the warning message (battery failure)\",\"bodySummary\":\"I have got this warning message on the System Management in a Proliant server 350ML G5.\\n\\nDegraded Accelerator\\nName    Value\\nStatus: Temporarily Disabled\\nError Code: Cache Disabled Low Batteries\\nSerial ...\",\"tags\":[\"hp-proliant\",\"hp-smart-array\"],\"lastActivityDate\":1427036609,\"url\":\"http://serverfault.com/questions/677390/smart-array-e200i-battery-on-350ml-did-not-fix-the-warning-message-battery-fail\",\"ownerUrl\":\"http://serverfault.com/users/164557/dlopezgonzalez\",\"ownerDisplayName\":\"dlopezgonzalez\",\"apiSiteParameter\":\"serverfault\"}"}
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"askubuntu.com\",\"id\":599889,\"titleEncodedFancy\":\"Is downgrading back to 14.04 from 14.10 possible?\",\"bodySummary\":\"I am using Ubuntu 14.10 alongside Windows 7 and I want to degrade to 14.04. I made a bootable pendrive using Universal USB Installer and seems like the pendrive is working fine. On the Installer Boot ...\",\"tags\":[\"14.04\",\"boot\",\"upgrade\",\"downgrade\"],\"lastActivityDate\":1427036610,\"url\":\"http://askubuntu.com/questions/599889/is-downgrading-back-to-14-04-from-14-10-possible\",\"ownerUrl\":\"http://askubuntu.com/users/374332/pkj\",\"ownerDisplayName\":\"pkj\",\"apiSiteParameter\":\"askubuntu\"}"}
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"superuser.com\",\"id\":814765,\"titleEncodedFancy\":\"External Harddrive Shutting Off and On Every So Often While Listening to Music\",\"bodySummary\":\"I am always listening to music on my PC (always via VLC Player) and every so often - maybe once every 2 songs, sometimes more frequently- the music stops playing (VLC's buffer/progress bar stops ...\",\"tags\":[\"hard-drive\",\"power\",\"external\"],\"lastActivityDate\":1427036610,\"url\":\"http://superuser.com/questions/814765/external-harddrive-shutting-off-and-on-every-so-often-while-listening-to-music\",\"ownerUrl\":\"http://superuser.com/users/338547/supercookie47\",\"ownerDisplayName\":\"SuperCookie47\",\"apiSiteParameter\":\"superuser\"}"}
    Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"math.stackexchange.com\",\"id\":1200778,\"titleEncodedFancy\":\"Continuity of a piecewise function at a specific point\",\"bodySummary\":\"I am having trouble proving the following function is not continuous at $x = 0$ using a formal definition of continuity.\\n\\n$\\nf(x) = \\\\left\\\\{\\n  \\\\begin{array}{lr}\\n    \\\\sin(\\\\frac{1}{x}) &amp; : x \\\\neq 0\\\\\\\\\\n ...\",\"tags\":[\"real-analysis\",\"functions\",\"continuity\",\"epsilon-delta\"],\"lastActivityDate\":1427036612,\"url\":\"http://math.stackexchange.com/questions/1200778/continuity-of-a-piecewise-function-at-a-specific-point\",\"ownerUrl\":\"http://math.stackexchange.com/users/222744/george\",\"ownerDisplayName\":\"George\",\"apiSiteParameter\":\"math\"}"}
    

    所以我想如果你想要一个用java运行的web套接字客户端,我想你可以接受所有证书,就像@tinker给你的链接一样。

    代码应该是这样的。也许你可以试试看在你的地方发生了什么。

    import java.net.URI;
    import java.security.cert.X509Certificate;
    import java.util.concurrent.Future;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.eclipse.jetty.websocket.api.Session;
    import org.eclipse.jetty.websocket.api.WebSocketAdapter;
    import org.eclipse.jetty.websocket.client.WebSocketClient;
    
    public class Main extends WebSocketAdapter {
    
        public static void main(String[] args) {
        String url = "wss://qa.sockets.stackexchange.com/"; // or
                                // "wss://echo.websocket.org"
    SslContextFactory sslContextFactory = new SslContextFactory();
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
        }
    
        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    
        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    } };
    try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        sslContextFactory.setSslContext(sc);
        WebSocketClient client = new WebSocketClient(sslContextFactory);
    
        client.start();
        Future<Session> fut = client.connect(new Main(), URI.create(url));
        Session session = fut.get();
        session.getRemote().sendString("Hello");
        session.getRemote().sendString("155-questions-active");
    } catch (Throwable t) {
        t.printStackTrace(System.err);
    }
    }
    
    @Override
    public void onWebSocketConnect(Session sess) {
    super.onWebSocketConnect(sess);
    System.out.println("Socket Connected: " + sess);
    }
    
    @Override
    public void onWebSocketText(String message) {
    super.onWebSocketText(message);
    System.out.println("Received TEXT message: " + message);
    }
    
    @Override
    public void onWebSocketClose(int statusCode, String reason) {
    super.onWebSocketClose(statusCode, reason);
    System.out.println("Socket Closed: [" + statusCode + "] " + reason);
    }
    
    @Override
    public void onWebSocketError(Throwable cause) {
    super.onWebSocketError(cause);
    cause.printStackTrace(System.err);
    }
    } 
    
        3
  •  3
  •   Sonny    10 年前

    这是我的Tyrus java客户端,我使用存根连接到运行HTTPS的Jetty 9.3.6服务器,该服务器使用自签名证书(改编自 Tyrus websocket client ,第8.1节):

                client = ClientManager.createClient();
    
                //System.getProperties().put("javax.net.debug", "all"); // Useful for debugging SSL interaction
                // The keystore in the next two lines is the same keystore you used for running the server,
                // likely in ${jetty.base}/etc/keystore
                System.getProperties().put(SSLContextConfigurator.KEY_STORE_FILE, "/tmp/keystore");
                System.getProperties().put(SSLContextConfigurator.TRUST_STORE_FILE, "/tmp/keystore");
                // The following two passwords are what you used for your self-signed cert
                System.getProperties().put(SSLContextConfigurator.KEY_STORE_PASSWORD, "HumanReadablePassword");
                System.getProperties().put(SSLContextConfigurator.TRUST_STORE_PASSWORD, "HumanReadablePassword");
                final SSLContextConfigurator defaultConfig = new SSLContextConfigurator();
    
                defaultConfig.retrieve(System.getProperties());
                // or setup SSLContextConfigurator using its API.
    
                SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(defaultConfig, true, false, false);
                client.getProperties().put(GrizzlyEngine.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
                client.connectToServer(sillyWebSocketClient , ClientEndpointConfig.Builder.create().build(),
                                       new URI("wss://localhost:8443/sillyWebSocketServer/echo"));
                System.out.println ("Connected .... ");
    

    哪里 SillyWebSocketClient sillyWebSocketClient 延伸 javax.websocket.Endpoint .

    我使用的是Java 8/Gradle 2.7环境 build.gradle 看起来像这样:

    apply plugin: 'java'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
          compile 'javax:javaee-api:7.0'
          compile 'org.glassfish.grizzly:grizzly-core:2.3.23'
          compile 'org.glassfish.tyrus:tyrus-container-grizzly:1.2.1'
          compile 'org.glassfish.tyrus:tyrus-client:1.6'
          compile 'javax.websocket:javax.websocket-client-api:1.1'
    }
    

    希望这有帮助。

    推荐文章