java - 如何在 Jetty Websocket 中访问 TLS 证书

标签 java ssl jetty

我有一个 TLS 安全连接,在该连接之上通过 Web 套接字执行通信。我想要做的是检查用于 TLS 连接的证书中包含的属性。

Jetty 用于 HTTP 通信,协议(protocol)将作为 karaf 组件运行。

我试图尽可能深入地挖掘各个层次。我希望在 WebsocketComponentServlet 中找到一些东西。至少有 ServletUpgradeRequest:

public class WebsocketComponentServlet extends WebSocketServlet {
    @Override
    public void configure(WebSocketServletFactory factory) {
        factory.setCreator(new WebSocketCreator() {
        @Override
        public Object createWebSocket(ServletUpgradeRequest req,    ServletUpgradeResponse resp)             
            ...

我试图深入了解 HTTPSession 或 ServletUpgradeRequest,但我无法在那里找到证书信息。如果我继续往下看,我会看到至少包含 SSLContextParameters 的 WebsocketComponent。但除了正确设置的 keystore 密码外,大多数字段都是空的。 我是在朝着正确的方向前进,还是完全没有捕获要点?

编辑:我想我需要更具体一些。下面的答案(谢谢你)指出了部署和配置 jetty 的常用方法。我尝试从测试内部访问证书数据。我包含了源代码:

public class WssProducerConsumerTest extends CamelTestSupport {
    protected static final String TEST_MESSAGE = "Hello World!";
    protected static final int PORT = AvailablePortFinder.getNextAvailable();
    protected Server server;
    private Process tpm2dclient = null;
    private Process tpm2dserver = null;
    private Process ttp = null;
    private File socketServer;
    private File socketClient;
    protected List<Object> messages;
    private static String PWD = "password";

    public void startTestServer() throws Exception {
        // start a simple websocket echo service
        server = new Server(PORT);
        Connector connector = new ServerConnector(server);
        server.addConnector(connector);

        ServletContextHandler ctx = new ServletContextHandler();
        ctx.setContextPath("/");
        ctx.addServlet(TestServletFactory.class.getName(), "/*");

        server.setHandler(ctx);

        server.start();
        assertTrue(server.isStarted());      
    }

    public void stopTestServer() throws Exception {
        server.stop();
        server.destroy();
    }

    @Override
    public void setUp() throws Exception {

        ClassLoader classLoader = getClass().getClassLoader();
        URL trustStoreURL = classLoader.getResource("jsse/client-truststore.jks");
        System.setProperty("javax.net.ssl.trustStore", trustStoreURL.getFile());
        System.setProperty("javax.net.ssl.trustStorePassword", "password");
        startTestServer();
        super.setUp();
    }

    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        stopTestServer();
    }

    @Test
    public void testTwoRoutes() throws Exception {
        MockEndpoint mock = getMockEndpoint("mock:result");
        mock.expectedBodiesReceived(TEST_MESSAGE);

        template.sendBody("direct:input", TEST_MESSAGE);

        mock.assertIsSatisfied();
    }


    private static SSLContextParameters defineClientSSLContextClientParameters() {

        KeyStoreParameters ksp = new KeyStoreParameters();
        ksp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/client-keystore.jks").toString());
        ksp.setPassword(PWD);

        KeyManagersParameters kmp = new KeyManagersParameters();
        kmp.setKeyPassword(PWD);
        kmp.setKeyStore(ksp);

        KeyStoreParameters tsp = new KeyStoreParameters();
        tsp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/client-truststore.jks").toString());

        tsp.setPassword(PWD);

        TrustManagersParameters tmp = new TrustManagersParameters();
        tmp.setKeyStore(tsp);

        SSLContextServerParameters scsp = new SSLContextServerParameters();
        //scsp.setClientAuthentication(ClientAuthentication.REQUIRE.name());
        scsp.setClientAuthentication(ClientAuthentication.NONE.name());

        SSLContextParameters sslContextParameters = new SSLContextParameters();
        sslContextParameters.setKeyManagers(kmp);
        sslContextParameters.setTrustManagers(tmp);
        sslContextParameters.setServerParameters(scsp);


        return sslContextParameters;
    }

    private static SSLContextParameters defineServerSSLContextParameters() {
        KeyStoreParameters ksp = new KeyStoreParameters();
        ksp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/server-keystore.jks").toString());
        ksp.setPassword(PWD);

        KeyManagersParameters kmp = new KeyManagersParameters();
        kmp.setKeyPassword(PWD);
        kmp.setKeyStore(ksp);

        KeyStoreParameters tsp = new KeyStoreParameters();
        tsp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/server-truststore.jks").toString());
        tsp.setPassword(PWD);

        TrustManagersParameters tmp = new TrustManagersParameters();
        tmp.setKeyStore(tsp);

        SSLContextServerParameters scsp = new SSLContextServerParameters();
        //scsp.setClientAuthentication(ClientAuthentication.REQUIRE.name());
        scsp.setClientAuthentication(ClientAuthentication.NONE.name());

        SSLContextParameters sslContextParameters = new SSLContextParameters();
        sslContextParameters.setKeyManagers(kmp);
        sslContextParameters.setTrustManagers(tmp);
        sslContextParameters.setServerParameters(scsp);


       return sslContextParameters;
    }

    @Override
    protected RouteBuilder[] createRouteBuilders() throws Exception {
        RouteBuilder[] rbs = new RouteBuilder[2];

        // An ips consumer
        rbs[0] = new RouteBuilder() {
            public void configure() {

                // Needed to configure TLS on the client side
                WsComponent wsComponent = (WsComponent) context.getComponent("ipsclient");
                wsComponent.setSslContextParameters(defineClientSSLContextClientParameters());

                from("direct:input").routeId("foo")
                    .log(">>> Message from direct to WebSocket Client : ${body}")
                    .to("ipsclient://localhost:9292/echo")
                    .log(">>> Message from WebSocket Client to server: ${body}");
                }
        };

        // An ips provider
        rbs[1] = new RouteBuilder() {
            public void configure() {

                    // Needed to configure TLS on the server side
                    WebsocketComponent websocketComponent = (WebsocketComponent) context.getComponent("ipsserver");
                    websocketComponent.setSslContextParameters(defineServerSSLContextParameters());

                    // This route is set to use TLS, referring to the parameters set above
                    from("ipsserver:localhost:9292/echo")
                    .log(">>> Message from WebSocket Server to mock: ${body}")
                    .to("mock:result");
            }
        };
        return rbs;
    }
}

最佳答案

Note: the following answer will only work under the following conditions

  1. The ServerConnector has HTTPS/SSL/TLS support.
  2. The ServerConnector has an appropriate HttpConfiguration that specifies that its traffic is secure
  3. The ServerConnector has the SecureRequestCustomizer added to its HttpConfiguration (this does things such as populating the HttpServletRequest attributes with the various servlet spec details about the secure connection)
  4. The Request was received on this ServerConnector
  5. You terminate SSL/TLS at Jetty (if you terminate SSL/TLS before Jetty, then Jetty does not have access to this certificate information)

org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest 中有几个选项

关于java - 如何在 Jetty Websocket 中访问 TLS 证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40258333/

相关文章:

java - 为什么在 JAVA 中按位 AND with byte 这样做?

java - 常数时间内二叉搜索树的高度

java - 如何在 Spring boot 中手动配置 SSL 握手

eclipse - 如何停止 gwt 的嵌入式服务器

gwt - 设置上下文 java :comp/env in Jetty running inside GWT 2. 7

java - 在 Android 日期选择器中将最大日期设置为 30 天

java - 使用 Mockito 对流畅的界面进行单元测试

ssl - 当用户键入 https ://时,Nginx 无法正确重定向

php - 如何在没有任何 SSL 证书的情况下将 https 重定向到 http

java - 为什么 Jetty JSR356 在 checkOrigin 和修改握手方面表现不同