使用 socket.io 和 Laravel Echo 时如何保护私有频道?

Posted

技术标签:

【中文标题】使用 socket.io 和 Laravel Echo 时如何保护私有频道?【英文标题】:How to guard private channels when using socket.io and Laravel Echo? 【发布时间】:2017-06-24 12:09:45 【问题描述】:

这是我的server.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();

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

redis.psubscribe('*', function(err, count) 
    console.log(err, count);
);
redis.on('pmessage', function(subscribed, channel, message) 
    message = JSON.parse(message);
    io.emit(message.event, channel, message.data);
);

还有一个简单的事件:

class FieldWasUpdated implements ShouldBroadcast

    use InteractsWithSockets, SerializesModels;
    public $instance;
    public $key;
    public $value;

    public function __construct($instance, $key, $value)
    
        $this->instance = $instance;
        $this->key = $key;
        $this->value = $value;
    

    public function broadcastOn()
    
        return new PrivateChannel("model." . $this->instance->getModelType() . "." . $this->instance->id);
    

客户端连接socket.io:

Echo = new Echo(
    broadcaster: 'socket.io',
    host: window.location.hostname + ':3000'
);

然后监听事件(在 Blade 模板中):

var channel = "model. $instance->getModelType() . $instance->id ";
Echo.private(channel)
    .listen("FieldWasUpdated", function(e) 
        window.VueBus.$emit("updated", channel, e.key, e.value);
    )
    .listen("FieldBecameDisabled", function(e) 
        window.VueBus.$emit("disabled", channel, e.key);
    );

问题是:没有处理认证,任何用户都可以订阅这些频道。

Broadcast::channel("model.announcement.*", function($user, $id) 
    return false; // this function is not called
)

这是来自 Chrome 开发者控制台 (WebSocket) 的示例事件:

[
    "App\\Events\\FieldWasUpdated",
    "private-model.announcement.2",
    
        "instance":
        
            "type":"ANN_TYPE_MISSED_CALL",
            "status":"ANN_STATUS_CANCELLED",
            "name":"1233421",
            "phone":"+7(222)222-3322",
            "email":"sdgsg@mail.com",
            "message":"sdgdsgsdgdfdg",
            "requirement":null,
            "web_type":"ANN_WEB_TYPE_UNKNOWN",
            "url":null,
            "responsible_id":19,
            "recommender_id":18
        ,
        "key":"message",
        "value":"sdgdsgsdgdfdg"
    
]

同样没有/broadcast/auth URL,但BroadcastServiceProvider 调用了Broadcast::routes();,当浏览器加载时,不会调用/broadcast/auth

【问题讨论】:

尝试 Broadcast::channel("model.announcement.*", function($user, $id) abort(401); ) 【参考方案1】:

Laravel 文档在广播一章中对此进行了详细介绍:https://laravel.com/docs/5.5/broadcasting#presence-channels。 Authorizing Presence Channels 部分应该与私人频道相同。

【讨论】:

以上是关于使用 socket.io 和 Laravel Echo 时如何保护私有频道?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5:使用 Laravel 会话数据的 Socket.io 客户端身份验证

Laravel 使用 Socket.io 广播到私人频道

使用 socket.io 和 Laravel Echo 时如何保护私有频道?

CORS、Laravel Valet 和 Socket.io

使用 Laravel Echo、laravel-echo-server 和 socket.io 广播将不起作用

尝试在 Laravel 的 vue.js 组件中导入 socket.io 时出现问题