PHP+;socket.io(会话、授权和安全问题)

PHP+;socket.io(会话、授权和安全问题),php,security,node.js,authentication,socket.io,Php,Security,Node.js,Authentication,Socket.io,我有一个正在运行的php应用程序,我想在其中添加实时支持。我想使用nodejs/socket.io来添加这种功能。 我发现的第一个问题是如何正确授权nodejs端的用户(用户已经通过php会话在php后端进行了身份验证)。使用nodejs端的socket.handshake.header.cookie,我可以解析并获取PHP会话id,我可以通过redis/memcache/database进行身份验证(取决于我用来保存会话信息的内容)。当用户注销时,他不应该在任何选项卡上收到任何消息(因为他已

我有一个正在运行的php应用程序,我想在其中添加实时支持。我想使用nodejs/socket.io来添加这种功能。

我发现的第一个问题是如何正确授权nodejs端的用户(用户已经通过php会话在php后端进行了身份验证)。使用nodejs端的socket.handshake.header.cookie,我可以解析并获取PHP会话id,我可以通过redis/memcache/database进行身份验证(取决于我用来保存会话信息的内容)。当用户注销时,他不应该在任何选项卡上收到任何消息(因为他已经从该浏览器注销了每个选项卡/窗口)。因此,在注销消息(在注销PHP之前从浏览器发送)中,我应该删除所有连接到授权用户id的套接字连接。但是,如果用户在两个设备(fe.pc浏览器和ipad safaris)上登录,该怎么办。在一台设备上注销后,他不应该在他注销的设备上收到任何消息,而不是在每台设备上如何区分socket.io中不同设备/浏览器的连接?当然,在这里不使用session\u regenate\u id()会很有效,但是如果我真的想使用此功能,我该怎么办?

我遇到的另一个问题是安全问题(甚至是问题)。让我们假设应用程序中的授权用户可以看到页面example.com/user1(这是user1的新闻提要),而不能看到example.com/user2(fe.他无权查看)。我希望socket.io在用户位于example.com/user1时向浏览器发送更新消息,当然,在用户位于example.com/user2站点时不发送更新消息。在socket.io端,我可以读取referer地址(因此,假设用户在user2站点上时,他没有获得任何socket.io连接)。问题是:我应该将referer地址与node.js端经过身份验证的用户的权限进行比较吗?或者referer值在node.js端是安全的?在node.js端添加另一个db检查会降低速度(因为几乎每个请求的两侧都应该有相同的数据库检查——PHP和node.js)。

或者,我所介绍的socket.io+PHP应用程序的整个概念是错误的

更新


我想我找到了一种省略第一个问题的方法——基本上我只是添加了另一个cookie(除了PHPSESSID)fe。命名为nodesssid,当用户获得授权时,我会生成它(fe.usinguniqid())。现在node.js端的授权正在比较PHPSESSID和NODESESSID(两者必须匹配)。现在,当用户注销时,他将消息logout发送到socket.io,socket.io将使用nodesssid断开所有套接字。这就像连接重新生成会话id和不重新生成会话id的好处一样(但不易受到会话固定的影响,不是吗?)

关于第二个问题:

如评论中所述,Referer不安全

我在我的应用程序中遇到了类似的问题,这就是它对我的作用

首先,我有一个单页应用程序,所有流量都通过套接字,但这不是必需的。它也应该以您管理会话的方式来处理会话

在nodejsonconnect中,我询问后端是否对用户进行了身份验证,然后将userid存储到socket对象(socket.data)中,并填充hashmap以直接从userid查找socket

其次,我使用Redis并从nodejs()订阅Redis列表。php后端使用用户ID推送此列表中的消息以寻址消息。nodejs接收此消息(例如,一个新的新闻提要项),在所提到的hashmap中查找userid并将其发送给客户端。因此,用户只能获得授权。然后,客户机决定如何处理该消息。如果用户在其提要页面上,则可以添加该项。如果用户在其他人的提要上,它可以简单地在页面的其他地方添加通知。它也可能丢弃它

在php后端站点上,每次发生需要在某个连接的客户端上实时显示的事件时,都会将这些消息发送到redis。如果user1在user2的提要上发布,则新项存储在数据库中,同时作为消息发送到redis队列中


这个系统也有助于减少数据库负载,因为NodeJ只需要查询数据库,以确保连接的用户已经通过身份验证。

实际上,您可以避免使用node.js,使用它,它是用php编写的,并且工作得很好。

我的猜测是,引用程序是从http头中获取的,所以我不认为它是安全的。我在第二个问题上有完全相同的问题,你偶然找到了解决方法吗?为什么不通过会话变量来控制页面的访问权限?例如,user1可以看到他的个人资料,但不能看到user2选择不公开的user2个人资料<代码>$\会话[“当前页面”]=”http://www.example.com/user1"; $_SESSION[“canview”]=检查nodejs上的用户权限($\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\。问题是关于节点和前端之间的安全问题(如何防止用户“入侵”referer address,在哪个节点上识别它必须发送的内容)。Vincent,不幸的是,除了在后端节点上再次检查权限之外,我没有找到任何其他方法