我需要访问 HttpServletRequest
属性以获取 javax.servlet.request.X509Certificate,其中包含用于 TLS 的 X509Certificate
证书数组请求。
从 JAX-RS ContainerRequestFilter
我可以很容易地从 ContainerRequestContext.getProperty(String property)
方法中提取它,但我找不到获取它的方法从 WebSocket Session
或 HandshakeRequest
,我可以从中访问 HttpSession
实例,但不能访问 HttpServletRequest
实例。
注意:这不是 Accessing HttpSession from HttpServletRequest in a Web Socket @ServerEndpoint 的副本因为我需要访问 HttpServletRequest
(或等同于提取 TLS 证书),而不是 HttpSession
。
由于 WebSocket 是 HTTP 的超集,我想它应该是可能的,希望 Java 团队已经想到了一种访问 servlet 属性的方法,但我真的找不到。有人知道这是否可能吗?
最佳答案
没有黑客:
- 在 URL 模式匹配 websocket 握手请求时创建 servlet 过滤器。
- 在过滤器中,获取感兴趣的请求属性并在继续链之前将其放入 session 中。
- 最后从 session 中获取它,而 session 又只能通过握手请求获得。
通过黑客攻击:
- 使用反射找到握手请求实例中的
ServletRequest
字段。 获取其
javax.servlet.request.X509Certificate
属性。换句话说:
public class ServletAwareConfigurator extends 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"); // ... } 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; } }
关于java - 在 WebSocket @ServerEndpoint 中访问 HttpServletRequest 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36184382/