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

时间:2017-12-19 21:33:58

标签: node.js laravel redis socket.io predis

我正在构建一个具有聊天功能的网络应用。我使用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);
});

1 个答案:

答案 0 :(得分:1)

尝试使用SSL (机密性)

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

身份验证(避免certificate pinning

如果您使用authenticationJWT,则需要HS256我强烈建议您在私有和公钥的情况下使用RS256 algorythm JWT

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

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

独特会话

由于您的服务使用JWT进行身份验证,因此您需要将authentication token发回给我们。这就像随机数或GUID一样简单。在此会话期间,此标识符将作为在此频道上发送或接收数据的任何请求的一部分,但只有在此特定频道上才会被接受,并且只有在此唯一会话开放时才会被接受。

再进行一次安全检查:链接reply attack

我向您提供了我每天使用的提示,以便与中央银行来回发送数据(因此遵循这些提示我认为您的应用应该非常安全)

<强>更新

如何处理 JWT

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

将路由分组到Verify JWT token中间件下!

创建RedisRepository这可以在App\RedisRepository下。该类应负责从redis中获取数据。

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

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