【问题标题】:Is it a good idea to use Sec-WebSocket-Key to identify the websocket client connection?使用 Sec-WebSocket-Key 来识别 websocket 客户端连接是个好主意吗?
【发布时间】:2013-08-15 23:31:41
【问题描述】:

在 servlet 世界中,我会使用 cookie 和 HttpSession 之类的东西来识别谁在访问我的 restful 服务以将请求路由到正确的数据。使用 Sec-WebSocket-Key 是否是一个好主意,就好像它是一个识别客户端连接的 cookie?

具体来说,我正在使用 socko scala 库(基于 netty 的 akka 网络服务器)从 socko-examples 的演示应用程序开始实现 websocket 服务器。 Socko 包装了一个 netty Channel 并将一个 netty WebSocketFrame 传递到应用程序代码中。然后,我想根据我之前与最终用户数据(例如他们的购物篮)相关联的客户端连接的“某些身份”调度传入数据的帧。为此,我编写了扩展方法来公开 Sec-WebSocket-Key http 标头,就好像它是通过从原始 websocket 握手中挖掘出 http 标头而进入应用程序的对象的顶级属性:

package org.mashupbots.socko.examples.websocket

// pimp my library pattern to add extension method
object ChatWebSocketExtensions {
  import org.mashupbots.socko.events.WebSocketFrameEvent

  class WebSocketFrameEventWithSecWebSocketKey(wsFrame: WebSocketFrameEvent) {
    def secWebSocketKey: String = { 
      wsFrame.initialHttpRequest.headers.get("Sec-WebSocket-Key").getOrElse("null") 
    }
  }
  implicit def webSocketFrameEventWithSecWebSocketKey(wsFrame: WebSocketFrameEvent) = new WebSocketFrameEventWithSecWebSocketKey(wsFrame)

  import org.mashupbots.socko.events.WebSocketHandshakeEvent;

  class WebSocketHandshakeEventWithSecWebSocketKey(event: WebSocketHandshakeEvent) {
    def secWebSocketKey: String = {
      val option = Option(event.nettyHttpRequest.getHeader("Sec-WebSocket-Key"))
      return option.getOrElse("null");

    }
  }
  implicit def webSocketHandshakeEventWithSecWebSocketKey(event: WebSocketHandshakeEvent) = new WebSocketHandshakeEventWithSecWebSocketKey(event)

}

这只是一些语法糖,因此应用程序代码不必在低级对象中挖掘来获取 Sec-WebSocket-Key 标头并像访问它一样访问它,就好像它是一流的属性一样:

  val routes = Routes({
    case WebSocketHandshake(wsHandshake) => wsHandshake match {
      case GET(PathSegments("websocket" :: roomNumber :: Nil)) => {
        log.info("Handsake to join room " + roomNumber)
        wsHandshake.authorize(onComplete = Some((event: WebSocketHandshakeEvent) => {
          val identity = event.secWebSocketKey;
          log.info("Authorised connection:" + identity);
          // do something with this identified user connection
        }))
      }
    }

    case WebSocketFrame(wsFrame) => {
      // Once handshaking has taken place, we can now process frames sent from the client
      val identity = wsFrame.secWebSocketKey;
      log.info("chat from:" + identity);
      // do something with this identified data frame
    }

  })

我的问题是,这是一种好的做法还是有更好的方法来识别用户连接?

【问题讨论】:

  • 我读的是文字,而不是代码。我正在寻找类似的解决方案。我想知道,会话管理是通过 HTTP 标头在 Tomcat 等中完成的,对吗?也许可以利用这一点?
  • 因为还没有 socko 的论坛,所以我在他们的问题跟踪器github.com/mashupbots/socko/issues/62 上指出了这个问题

标签: websocket netty


【解决方案1】:

“Sec-WebSocket-Key”标识一个连接。

但是,我不太确定使用“Sec-WebSocket-Key”是否是识别“会话”的好主意。

这是因为 'Sec-WebSocket-Key' 不适应断开连接并要求客户端建立新连接的情况。可能会发布一个新的“Sec-WebSocket-Key”。用户将失去他/她的会话。

使用 HTTP,会话通常与 URL 中的 cookie 或 id 相关联——这两者都独立于 HTTP 连接。这样,一个用户会话可以使用多个 HTTP 连接。

我建议你为你的网络套接字“会话”使用类似的东西。

作为握手和成功登录的一部分,让服务器向客户端发送会话 ID。客户端应在每次请求时将会话 ID 发送回服务器。

这样,您可以使用像https://github.com/joewalnes/reconnecting-websocket 这样的javascript 在您的应用程序代码中提供网络弹性。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2016-06-28
    • 2015-05-22
    • 1970-01-01
    • 2013-08-18
    • 2014-04-17
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多