在WebSocket @ServerEndpoint中访问HttpServletRequest属性

3
我需要访问HttpServletRequest属性,以获取javax.servlet.request.X509Certificate,其中包含用于TLS请求的X509Certificate数组。
从JAX-RS ContainerRequestFilter中,我可以轻松地通过ContainerRequestContext.getProperty(String property)方法提取它,但我找不到一种方法可以从WebSocket的SessionHandshakeRequest中获取它,我可以从中访问HttpSession实例,但不能访问HttpServletRequest
注:这不是Accessing HttpSession from HttpServletRequest in a Web Socket @ServerEndpoint的重复,因为我需要访问HttpServletRequest(或相当等价的内容以提取TLS证书),而不是HttpSession
由于WebSocket是HTTP的一个超集,我想应该是可能的,并希望Java团队能够想出一种访问servlet属性的方法,但我真的找不到。有人知道是否可能吗?
1个回答

6

没有黑客攻击:

  1. 创建Servlet过滤器以匹配WebSocket握手请求的URL模式。
  2. 在过滤器中,获取感兴趣的请求属性并将其放入会话中,然后继续链。
  3. 最后从会话中获取它,而会话又可以通过握手请求轻松获得。

有黑客攻击:

  1. Use reflection to find ServletRequest field in handshake request instance.
  2. Get its javax.servlet.request.X509Certificate attribute.

    In other words:

    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;
        }
    
    }
    

谢谢@BalusC,这可能有效。如果可能的话,我宁愿不使用HttpSession。我想知道WebSocket是否实际上使用HttpServeltRequest,只是在其API中没有公开它或根本不使用它... - Giovanni Lovato
这是具体实现相关的。这正是为什么要“不以黑客方式” :) - BalusC
你说得对!顺便提一下,我正在使用WildFly/Undertow。如果WebSocket JSR在HandshakeRequest API中公开了javax.servlet.http.HttpSession,我真的不明白为什么它不会公开javax.servlet.http.HttpServletRequest… - Giovanni Lovato
没错。我的意思是,由于WebSocket可以通过TLS(wss://)访问,因此API应该公开一个路径来获取有关安全连接的信息,例如客户端X509证书(如HttpServletRequest中所示,即X509Certificate[] certs = (X509Certificate[]) request.getProperty("javax.servlet.request.X509Certificate"))。 - Giovanni Lovato
在WS规范的网站上发布一个问题,请求添加一个新的方法来完成至少这个任务:https://java.net/jira/browse/WEBSOCKET_SPEC - BalusC
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接