PHP + Redis + Pub / Sub + WebSockets(+ NodeJS)中的实时聊天

时间:2017-03-08 08:52:10

标签: php node.js redis publish-subscribe autobahn

我想与频道进行实时聊天,这些是我的需求:

  
      
  • PHP后端管理网站
  •   
  • Redis作为会话和数据主存储
  •   
  • 发布/订阅仅向频道的感兴趣的用户发送消息
  •   
  • 用于发送和接收消息的一个WebSocket连接。
  •   
  • (可选)NodeJS使用极好的npm包,如timesync或socket.io
  •   

我看到两种不同的架构来实现这一目标:

  • 使用Socket.io

    socket.io

  • 使用Crossbar.io

  • crossbar.io

以下是我的问题:

  1. 我应该选择哪种架构?为什么?
  2. 关键是无法从客户端获取用户ID,因为它可能格式不正确。所以在第一个架构中,我认为在每个套接字消息上我应该从cookie附加PHPSESSID值,并在服务器端从Redis检索PHP会话。我是对的还是有更好的方法来获取用户ID?
  3. 我想知道在第二个架构中获取用户ID是否可以采用不同的方式?
  4. 修改

    我选择了 Crossbar.io ,因为它功能非常强大,可以实时通信许多不同的语言应用程序。在研究了例子之后,我想出了这个:

    • 每个登录用户都在数据库中生成了密钥。

    • PHP客户端(高速公路)连接到Crossbar服务器并注册自定义WAMP-CRA验证器

    • 用户的浏览器连接到Crossbar服务器并受到质疑。 Secret和auth_id(用户id)是从带有页面加载的DB加载的,所以它 可以完成挑战并发送回应。

    • PHP身份验证器在DB中搜索提供的秘密和id等于auth_id的用户。如果有,则成功进行身份验证 会话。现在我们可以相信auth_id是真正的用户ID。

    这是我的问题:

    1. 如何在订阅时获取auth_id?

    2. 我还添加了cookie身份验证,并在身份验证后记住浏览器。但是,当我查看 Chrome DevTools 时,本地存储中存在任何cookie或值。即使在清除缓存后,我的浏览器仍然记得 Crossbar 。我想知道它是如何可能的?

    3. 编辑2:

      也许我被误解了,但主要的问题是选择合适的架构并获得可信赖的用户ID。没有人注意所以我给了赏金,之后我被投票了。我阅读了很多关于实时应用程序的内容,最后决定使用 Crossbar.io ,因此我编辑了与之相关的问题。然后人们开始提出建议,提出另一种架构,但并没有真正回答我的问题。毕竟我设法自己做了并提出了我的答案。

3 个答案:

答案 0 :(得分:1)

我深度照亮美国国家航空航天局(NASA)用于每秒转发卡车数据的Streamer。用于实时消息传递的最可靠的服务器。 支持Web,移动设备,平板电脑,桌面和物联网应用。

针对网络和移动设备的优化数据流。 Lightstreamer支持多种形式的实时消息传递。它足够灵活,可用于任何场景,包括关键任务应用程序。 ►实时数据推送和Web套接字 ►应用内消息传递和推送通知 ►Pub-sub,具有扇出广播和一对一消息 ►防火墙和代理友好 ►自适应带宽限制

关于在订阅时获取auth_id的第一个问题,只需监视连接订阅,然后在成功连接时存储层。 也不建议使用cookie,使用jwt.JSON Web Tokens是一种开放的,行业标准的RFC 7519方法,用于在两方之间安全地表示声明。身份验证是每个应用程序的重要组成部分之一。安全总是在变化和发展.JWT可以帮助您解决这个问题。因为它是无国籍的。

答案 1 :(得分:0)

PHP Ratchet是我用于通过WebSockets进行实时通信的最佳实现之一。它基于ZMQ套接字,用于多种在线游戏应用程序和聊天应用程序。

以下示例将让您快速入门,并将围绕auth_id和订阅回答您的问题:

http://socketo.me/docs/hello-world

http://socketo.me/docs/push

架构概述:

http://socketo.me/docs/push#networkarchitecture

我会建议为每个对话创建单独的连接(toppics),因为它不会真正影响性能,并且每次聊天都会增加额外的安全层。

答案 2 :(得分:0)

关于获取用户ID:

我看到的每个实时聊天示例都是从客户端获取id。这是不安全的,因为客户端很容易操纵它,所以我需要找到另一种方法。阅读WAMP specs之后,我终于发现我不仅要在应用程序中对用户进行身份验证,还要在 Crossbar.io 中对用户进行身份验证。我选择了动态WAMP-CRA方法并实现如下:

  • PHP应用程序连接到Crossbar服务器并注册自定义身份验证器(类似于example
  • 用户在app中登录后,会为他生成密钥并保存在数据库中。注销后,密钥将被销毁。
  • 工作流:

    1. 每个加载的页面都包含从db加载的用户ID 密钥

      <script>
          auth_id = '<?php echo $user->id ?>';
          secret_key = '<?php echo $user->secret_key ?>';
      </script>
      
    2. 用户浏览器连接到 Crossbar.io 服务器,并通过自定义身份验证器的挑战获得响应。
    3. 使用键计算签名并与 auth_id 一起发送到 Crossbar.io 服务器
    4. Authenticator从DB secret 获取提供的 auth_id 并计算签名。然后比较签名,如果它们相等则认证成功。
    5. 现在 auth_id 包含用户ID,我们可以信任它的值。现在您可以参考'如何在订阅时获得auth_id 部分。

的答案:

  

如何在订阅时获得auth_id?

默认情况下,发布者和订阅者对彼此没有任何了解,但documentation显示可以通过配置来电者身份的披露来更改它。然后你可以从回调细节中获取auth_id:

  • PHP:

    $onEvent = function ($args, $argsKw, $details, $publicationId) use ($session) {
        $auth_id = $details->publisher_authid;
        ...
    }
    $session->register('com.example.event', $onEvent);
    
  • JS:

    function on_event(args, kwargs, details) {
        auth_id = details['publisher_authid'];
        ...
    }
    session.subscribe('com.example.event', on_event);
    
  

我还添加了cookie身份验证,并在身份验证后记住浏览器。但是,当我查看Chrome DevTools时,本地存储中存在任何cookie或值。即使在清除缓存后,我的浏览器仍然会被Crossbar记住。我想知道它是如何可能的?

首先,清除缓存和硬重新加载不会删除cookie。当我问这个问题时,有任何cookie呈现,但今天我可以看到cbtidcookies 两天前有Chrome更新,所以这可能是由以前版本中的错误引起的。