如何保护Redis&Socket.IO实时服务器,以便只有经过身份验证的用户才能收听?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何保护Redis&Socket.IO实时服务器,以便只有经过身份验证的用户才能收听?相关的知识,希望对你有一定的参考价值。

我正在构建一个具有聊天功能的网络应用。我使用Laravel 5.4作为后端,Angular 4作为前端。

一切正常(意味着我可以播放和接收),但我不确定如何保护它。聊天将始终是1比1,所以它是私人的,必须是安全的。每个聊天室都有一个唯一的ID,但有人仍然可以收听。

目前,当我从我的前端向我的API发出请求时,我正在使用JWT进行身份验证,但我不确定是否可以为此实现类似的功能。我知道我可以使用query选项从前端传递令牌,但我不确定如何解析它,我也不确定如何验证它确实属于试图访问聊天的用户(我应该请求API在server.js中验证?这看起来效率不高。将令牌的用户ID与将在数据中传递的用户ID进行比较是否足够好?)

如果有人有任何建议或知道更好的方法,那将会非常有用

发布新消息时从Laravel发起的事件

class NewMessage implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $data;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->data = array(
            'message'=> 'hi'
        );
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('chat');
    }

}

server.js(node.js)

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();

redis.psubscribe('private-chat', function(err, count) {
    console.log('psubscribe');
});


redis.on('pmessage', function(subscribed, channel, message) {
    console.log('pmessage', subscribed, channel, message);
    message = JSON.parse(message);
    io.emit(channel + ':' + message.event, message.data);
});

http.listen(3000, function(){
    console.log('Listening on Port 3000');
});

前端组件

socket: io.Socket;
this.socket = io.connect("http://webapp.test:3000",  { query: this.token });
this.socket.on("private-chat:App\Events\NewMessage", (data) =>
{
  console.log("Data", data);
});
答案

尝试使用SSL(机密性)

我们知道SSL确保您正在与之通信的服务器实际上是您想要的Web服务。

身份验证(避免certificate pinning

在你使用authenticationJWT的情况下你需要HS256,我强烈建议你在这种情况下使用RS256 algorythm JWT私钥和公钥。

如果您不确定谁在另一端(身份验证),那么没有其他人可以听你们俩之间的对话并不重要。

因为我将以如下方式构建应用程序:如果两个通道之间的会话authentication未设置,则永远不会展开正在发送的数据的内容。

独特的会话

因为slong作为你的服务使用JWT认证你送回他们authentication token。这就像随机数或GUID一样简单。在此会话期间,此标识符将作为在此通道上发送或接收数据的任何请求的一部分,但只有在此特定会话打开时才会在此特定通道上接受。

还有一项安全检查:链接reply attack

我给了你每天使用的提示,以安全地与中央银行来回发送数据(所以遵循这些提示,我认为你的应用应该非常安全)

UPDATE

如何处理JWT

创建一个新的中间件qazxsw poi,因为laravel中的中间件是核心供应商的外层,这意味着如果身份验证失败,它就会在核心层中的外层失败。

Verify JWT token中间件下分组路线!

创建一个Verify JWT token,这可能是在RedisRepository下。该类应负责从redis获取数据。

在中间件解密用户JWT上获取解密的有效负载(这可能是用户UUID或ID)。

如果正认证通过,则从RedisRepository获取AppRedisRepository与解密的有效负载进行比较,否则中止403未经认证!

以上是关于如何保护Redis&Socket.IO实时服务器,以便只有经过身份验证的用户才能收听?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 socket.io-redis 发送私人消息(发射)

Socket.io & Redis - 适合 io 游戏的架构?

Node.js、Socket.io、Redis pub/sub 大容量、低延迟困难

如何在前端获取 socket.on 函数?事件被触发和处理。我正在使用 socket.io、NodeJS 服务器和 Redis.io

Vue.js 如何使用 Socket.IO?

使用 Socket.io 和 Redis 的节点集群问题