如何在 Jetty Websocket 中访问 TLS 证书
How to access TLS certificates in Jetty Websocket
我有一个 TLS 安全连接,在该连接之上通过 Web 套接字执行通信。我想要做的是检查用于 TLS 连接的证书中包含的属性。
Jetty 用于 HTTP 通信,协议将 运行 作为 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。但除了正确设置的密钥库密码外,大多数字段都是空的。
我是在朝着正确的方向前进,还是完全没有抓住要点?
编辑:我想我需要更具体一些。下面的答案(谢谢你)指出了部署和配置码头的常用方法。我尝试从测试内部访问证书数据。我包含了源代码:
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
- The
ServerConnector
has HTTPS/SSL/TLS support.
- The
ServerConnector
has an appropriate HttpConfiguration
that specifies that its traffic is secure
- 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)
- The Request was received on this
ServerConnector
- 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
中有几个选项
getCertificates()
returns X509Certificate[]
链
getServletAttribute("javax.servlet.request.ssl_session_id")
returns 表示 SSLSession ID 的字符串
getServletAttribute("javax.servlet.request.cipher_suite")
returns 表示 SSLSession 密码套件的字符串
getServletAttribute("javax.servlet.request.key_size")
returns 表示密码套件密钥长度的整数
getServletAttribute("javax.servlet.request.X509Certificate")
returns 证书链正在使用中
我有一个 TLS 安全连接,在该连接之上通过 Web 套接字执行通信。我想要做的是检查用于 TLS 连接的证书中包含的属性。
Jetty 用于 HTTP 通信,协议将 运行 作为 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。但除了正确设置的密钥库密码外,大多数字段都是空的。 我是在朝着正确的方向前进,还是完全没有抓住要点?
编辑:我想我需要更具体一些。下面的答案(谢谢你)指出了部署和配置码头的常用方法。我尝试从测试内部访问证书数据。我包含了源代码:
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
- The
ServerConnector
has HTTPS/SSL/TLS support.- The
ServerConnector
has an appropriateHttpConfiguration
that specifies that its traffic is secure- The
ServerConnector
has theSecureRequestCustomizer
added to itsHttpConfiguration
(this does things such as populating theHttpServletRequest
attributes with the various servlet spec details about the secure connection)- The Request was received on this
ServerConnector
- 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
getCertificates()
returnsX509Certificate[]
链getServletAttribute("javax.servlet.request.ssl_session_id")
returns 表示 SSLSession ID 的字符串getServletAttribute("javax.servlet.request.cipher_suite")
returns 表示 SSLSession 密码套件的字符串getServletAttribute("javax.servlet.request.key_size")
returns 表示密码套件密钥长度的整数getServletAttribute("javax.servlet.request.X509Certificate")
returns 证书链正在使用中