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

Real time chat in PHP +Redis +Pub/Sub +WebSockets (+NodeJS)

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

  • PHP backend to manage site
  • Redis as session and data primary storage
  • Pub/Sub to send messages only to channel's interested users
  • one WebSocket connection with which the messages will be send and received.
  • (optional) NodeJS to use great npm packages like timesync or socket.io

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

这些是我的问题:

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

编辑:

我选择了Crossbar.io,因为它非常强大,可以实时交流多种不同语言的应用程序。研究示例后,我想出了这个:

这些是我的问题:

  1. 如何订阅才能获得 auth_id?

  2. 我还添加了cookie认证,认证后会记住浏览器。但是当我查看 Chrome DevTools 时,本地存储中没有任何 cookie 或值。即使在清除缓存后,Crossbar 仍然记得我的浏览器。我想知道这怎么可能?

编辑2:

也许我被误解了,但主要问题是选择合适的架构并获得受信任的用户 ID。没有人注意所以我奖励了赏金,然后我被否决了。我阅读了很多关于 real-time 应用程序的文章,最后决定使用 Crossbar.io,所以我编辑了与之相关的问题。然后人们开始投票,提出另一种架构,但并没有真正回答我的问题。毕竟我自己设法做到了并提出了我的答案。

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

以下示例将帮助您快速入门,并将回答您有关 auth_id 和订阅的问题:

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

http://socketo.me/docs/push

架构概述:

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

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

我深深点亮了 Streamer,NASA 使用它来为每个 second.The 最可靠的实时消息传递服务器转发大量数据。 为网络、手机、平板电脑、桌面和物联网应用程序提供动力。

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

关于在订阅上获得 auth_id 的第一个问题,只需监视连接订阅,然后在成功连接后存储层。 此外,不推荐使用 cookie,使用 jwt.JSON Web 令牌是一种开放的行业标准 RFC 7519 方法,用于在两个 parties.Authentication 之间安全地表示声明是每个应用程序的重要组成部分之一。安全性总是在变化,evolving.JWT 帮助您解决 concern.Since 它是无状态的问题。

关于获取用户id:

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

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

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

      加载
      <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,我们可以相信它的值。现在你可以参考'How I can get auth_id on subscribe?'.
    6. 部分

答案:

How I can get auth_id on subscribe?

默认情况下,发布者和订阅者彼此不了解,但 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);
    

I also added cookie authentication and browser is remembered after authentication. But when I look in Chrome DevTools there is any cookie nor value in local storage. Even after clearing cache my browser is still remember by Crossbar. I wonder how it is possible?

首先,清除缓存和硬重新加载不会删除 cookie。当我问这个问题时,出现了任何 cookie,但今天我可以看到 cbtid 两天前有Chrome更新,所以这可能是之前版本的bug造成的。