【问题标题】:Accessing HttpServletRequest properties within a WebSocket @ServerEndpoint在 WebSocket @ServerEndpoint 中访问 HttpServletRequest 属性
【发布时间】:2016-03-23 17:02:07
【问题描述】:

我需要访问 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 属性的方法,但我真的找不到。有人知道这是否可能吗?

【问题讨论】:

    标签: java servlets jakarta-ee websocket java-websocket


    【解决方案1】:

    没有黑客攻击:

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

    黑客攻击:

    1. 使用反射在握手请求实例中查找ServletRequest 字段。
    2. 获取其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;
          }
      
      }
      

    【讨论】:

    • 谢谢@BalusC,这可以工作。如果可能的话,我宁愿不使用HttpSession。我想知道 WebSocket 是否真的使用 HttpServeltRequest 并且只是没有在其 API 中公开它或者根本不使用它......
    • 它是特定于实现的。这正是“没有黑客攻击”的原因:)
    • 你是对的!顺便说一句,我在 WildFly/Undertow 上。如果 WebSocket JSR 在HandshakeRequest API 中公开javax.servlet.http.HttpSession,我真的不明白为什么它不公开javax.servlet.http.HttpServletRequest...
    • WS 握手不是根据 HTTP servlet 请求触发的定义。所以它不能暴露在 API 中(否则,极度紧耦合和不可重用的 API)。基本上,它应该暴露出一种getAttribute()/getAttributeMap() orso。
    • 再次正确。我的意思是,由于 WebSocket 可以通过 TLS (wss://) 访问,API 应该公开一个路径以获取有关安全连接的信息,例如客户端 X509 证书(如HttpServletRequest,即X509Certificate[] certs = (X509Certificate[]) request.getProperty("javax.servlet.request.X509Certificate"))。
    猜你喜欢
    • 2013-07-29
    • 1970-01-01
    • 2015-02-28
    • 2012-12-15
    • 2018-12-13
    • 1970-01-01
    • 2017-05-31
    • 2014-03-20
    相关资源
    最近更新 更多