连接到安全的websocket

cau*_*aub 8 java jetty tyrus

我正在尝试使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

    }
}
Run Code Online (Sandbox Code Playgroud)

相比之下,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');
});
Run Code Online (Sandbox Code Playgroud)

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

Joa*_*elt 13

有一种更简单的方法,无需混淆信任商店,定制X509TrustManagers或定制SSLContexts.

只需使用SslContextFactory已有的......

package jetty.websocket;

import java.net.URI;
import java.util.concurrent.Future;

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 sslContextFactory = new SslContextFactory();
        sslContextFactory.setTrustAll(true); // The magic

        WebSocketClient client = new WebSocketClient(sslContextFactory);
        try
        {
            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);
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个会有这样的结果......

2015-03-26 06:46:34.893:INFO::main: Logging initialized @62ms
2015-03-26 06:46:35.700:INFO:jw.SecureClientSocket:WebSocketClient@1849650547-15: onConnect(WebSocketSession[websocket=JettyAnnotatedEventDriver[jetty.websocket.SecureClientSocket@c299bbd],behavior=CLIENT,connection=WebSocketClientConnection@7faf9b87{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],p=Parser@7a65105a[ExtensionStack,s=START,c=0,len=0,f=null,p=WebSocketPolicy@114c37d[behavior=CLIENT,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},remote=WebSocketRemoteEndpoint@7a2e4418[batching=true],incoming=JettyAnnotatedEventDriver[jetty.websocket.SecureClientSocket@c299bbd],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]])
2015-03-26 06:46:39.464:INFO:jw.SecureClientSocket:WebSocketClient@1849650547-14: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"math.stackexchange.com\",\"id\":1207542,\"titleEncodedFancy\":\"Do we have this type of integral expression of Bessel function of the first kind?\",\"bodySummary\":\"Let $z=\\\\lambda+i\\\\mu$ with $\\\\mu&gt;0$. Then for any $r&gt;0$, $k=1,2,3, \\\\cdots$. Do we have the following identity\\n$$\\n\\\\int_{r}^{\\\\infty}{\\\\frac{t}{\\\\sqrt{t^2-r^2}}(\\\\frac{1}{t}\\\\frac{d}{dt})^k ...\",\"tags\":[\"analysis\",\"reference-request\",\"special-functions\"],\"lastActivityDate\":1427377599,\"url\":\"http://math.stackexchange.com/questions/1207542/do-we-have-this-type-of-integral-expression-of-bessel-function-of-the-first-kind\",\"ownerUrl\":\"http://math.stackexchange.com/users/37742/sun\",\"ownerDisplayName\":\"sun\",\"apiSiteParameter\":\"math\"}"}
2015-03-26 06:46:41.469:INFO:jw.SecureClientSocket:WebSocketClient@1849650547-16: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"drupal.stackexchange.com\",\"id\":152924,\"titleEncodedFancy\":\"Features can export everything?\",\"bodySummary\":\"Built all blocks, menu, taxonomies, view etc in Drupal CMS on localhost machine, but I need to export everything to the live server. Is it possible to use features or just export sql?\\n\",\"tags\":[\"theming\"],\"lastActivityDate\":1427377601,\"url\":\"http://drupal.stackexchange.com/questions/152924/features-can-export-everything\",\"ownerUrl\":\"http://drupal.stackexchange.com/users/34551/joe\",\"ownerDisplayName\":\"joe\",\"apiSiteParameter\":\"drupal\"}"}
2015-03-26 06:46:44.034:INFO:jw.SecureClientSocket:WebSocketClient@1849650547-13: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"wordpress.stackexchange.com\",\"id\":182350,\"titleEncodedFancy\":\"Create page from plugin, but have it completely hidden\",\"bodySummary\":\"I need to have a plugin create a page that is publicly accessible, but does NOT show up in the admin section anywhere, and cannot be deleted or modified.\\n\\nI thought maybe figuring out a way to have a ...\",\"tags\":[\"plugins\",\"pages\"],\"lastActivityDate\":1427377603,\"url\":\"http://wordpress.stackexchange.com/questions/182350/create-page-from-plugin-but-have-it-completely-hidden\",\"ownerUrl\":\"http://wordpress.stackexchange.com/users/45132/joel-worsham\",\"ownerDisplayName\":\"Joel Worsham\",\"apiSiteParameter\":\"wordpress\"}"}
Run Code Online (Sandbox Code Playgroud)