我有一个在Tomcat中运行的Java应用程序。我在端口8443上添加了https侦听器,如下所述:
https://docs.spring.io/spring-boot/docs/2.2.x/reference/pdf/spring-boot-reference.pdf(9.3.13。使用Tomcat启用多个连接器)
我还配置了侦听器,以挑战客户端出示证书(2-way-TLS /双向TLS)并拥有一个带有可信条目的信任库。所有这些都有效,我可以在日志中看到整个TLS握手以及提供的客户端证书。
我有一个WebSocket服务器端点(@javax.websocket.server.ServerEndpoint
),当安全tls隧道建立后,当客户端通过“ wss:// .....”连接时,确实会调用该端点,{{1} }方法被调用,它具有javax.websocket.Session对象。因此将http(s)升级到ws即可。
我的问题: 执行TLS握手后(由WSS触发:在我的情况下为ws over https),我需要提取客户端证书(X509)信息(主题/发布者等。),并在@OnOpen方法中提供它。我正在寻找某些拦截器或其他方式来访问和提取证书数据,并在升级到ws后 使其可用。有什么方法可以通过@OnOpen
Web套接字处理方法访问HttpServletRequest
?感谢您的帮助。
答案 0 :(得分:0)
再看一下我就能做到了。
第1步:进入ModifyHandshake(...)方法并获得ServletRequest
对象,HttpSession
将无法完成工作。积分转到this StackOverflow answer。
package example.com;
import java.lang.reflect.Field;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class InjectAttributesIntoWebSocketConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
ServletRequest servletRequest = getField(request, ServletRequest.class);
X509Certificate[] certificates = (X509Certificate[]) servletRequest.getAttribute("javax.servlet.request.X509Certificate");
// certificates[0] is client certificate
// do null/error/empty array handling here
config.getUserProperties().put("clientcert", certificates[0]);
}
private static <I, F> F getField(I instance, Class<F> fieldType) {
try {
for (Class<?> type = instance.getClass(); type != Object.class; type = type.getSuperclass()) {
for (Field field : type.getDeclaredFields()) {
if (fieldType.isAssignableFrom(field.getType())) {
field.setAccessible(true);
return (F) field.get(instance);
}
}
}
} catch (Exception e) {
// Handle?
}
return null;
}
}
第2步:将WS配置为使用上面的配置器,并从Session
对象中读取任何参数(您必须事先将这些参数添加到ModifyHandshake()方法中)。
@ServerEndpoint(
value = "/some/endpoint/here",
configurator = InjectAttributesIntoWebSocketConfigurator.class
)
第3步:完成:)。现在,WS端点具有客户端证书,通过该客户端证书建立了基础HTTPS连接TLS(在我的情况下为2-way TLS)。