我有一个Web应用程序,我的用户已经在HTTP中进行了身份验证。 HTTP身份验证后,我想接收视频通话。为此,我选择了一个WebSockets服务器(我编写了一个小的PHP CLI脚本)。
有一个问题,我找不到在我的WebSocket守护程序上验证经过身份验证的用户的方法。 (因为它是CLI应用程序,它适用于每个实例的许多用户。)
我想,将用户在握手请求中发送的标头提供给我的WebSocket服务器是个好主意。我解析了Cookie并使用session_id()
和session_start()
创建了一个会话,但我不能为多个用户执行此操作,仅针对一个用户。
在许多主板上都有建议通过JS发送用户ID和一些密钥来识别用户身份,但这并不安全。也许我可以使用哈希用户密码发送用户ID,我将以html(js内联常量)存储在某处?你觉得怎么样?
在WebSocket服务器上验证用户的最佳方法是什么?请记住,此用户已使用HTTP进行身份验证。
答案 0 :(得分:0)
我强烈建议您单独留下密码。不要通过WebSockets连接传递它。一旦用户通过任何一种方式进行了身份验证,请不要再使用他们的密码。
你是对的,你不能在服务器的同一个实例中为多个用户使用session_start()
。相反,您必须单独存储用户的数据并将其与其TCP套接字句柄相关联。 (TCP套接字句柄是socket_accept()
)返回的值。
例如,在WebSockets服务器中,有一个用户类,您可以在其中为每个连接实例化一个新对象。
此用户对象将在其连接时保持其状态。用户对您的Web应用程序进行身份验证后,在HTTP响应中发送唯一的cryptographically secure token,在HTTP标头中或在正文中,例如在HTML头中元素的属性中, Javascript中指定的值,或者对您有意义的地方。还可以将此唯一值存储在WebSockets服务器可以访问的位置,以及分配给它的用户和时间戳。
在客户端Javascript中,一旦建立了WebSockets连接,就发送安全令牌。
在服务器端,只需将令牌与您的Web脚本存储的令牌进行比较,并确保时间戳是最近的。这将告诉您哪个用户刚刚登录,并允许您将他们的首选项从数据库中提取出来。
关于时间戳到期的说明:WebSockets意味着是一个实时通信系统,在大多数情况下,WebSockets连接是在页面加载期间或onload
事件后不久建立的。除非您在打开WebSockets连接之前等待用户交互,否则接受超过几分钟的令牌是没有意义的。为避免会话劫持尝试,请仅接受使用特定令牌的第一个连接,并且不接受旧令牌。
一旦它们连接起来,您就可以至少确定用户的身份,就像您使用$ _SESSION变量一样,只要它们保持连接。 (TCP劫持可能会发生,但是攻击者已经进行了MITM攻击,并且在TCP劫持开始之前很久就会完全破坏他们的PHP会话。)