使用Sec-WebSocket-Key识别websocket客户端连接是一个好主意吗?

sim*_*905 3 websocket netty

在servlet世界中,我会找到像cookies和HttpSession这样的东西来识别谁正在使用我的restful服务来将请求路由到正确的数据.使用Sec-WebSocket-Key是一个好主意,好像它是一个识别客户端连接的cookie?

具体来说,我使用socko scala库(基于netty的akka​​ webserver)从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)

}
Run Code Online (Sandbox Code Playgroud)

这只是一些语法糖,因此应用程序代码不必在低级别对象中挖掘以获取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
    }

  })
Run Code Online (Sandbox Code Playgroud)

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

Vee*_*ebs 6

'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 在应用程序代码中提供网络弹性.

希望这可以帮助.