php - 通过 socket.io 为广播频道授权 laravel 护照
问题描述
我正在使用laravel 5.3
+ 护照进行授权,Laravel
我的后端 API 是restful
.
前端是写在angular.js
其中与 API 进行通信以进行休息请求。
对于实时通知,我使用了laravel
广播事件 + redis
,socket.io
对于套接字服务器和套接字客户端angular.js.
我想授权这些事件,我已经尽我所能:
广播服务提供者:
public function boot()
{
Broadcast::routes(['middleware' => ['auth:api']]);
Broadcast::channel('App.User.*', function ($user, $userId)
{
return (int) $user->id === (int) $userId;
});
Broadcast::channel('notifs.*', function ($user, $userId) {
return $user->id === (int) $userId;
});
}
这是我的 socket.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('*', function(err, count) {});
redis.on('pmessage', function(subscribed, channel, message) {
console.log(channel);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function () {
console.log('Listening on Port 3000');
});
redis.on("error", function (err) {
console.log(err);
});
问题是我不知道如何在套接字服务器中验证这些广播事件,也不知道如何授权用户angular.js (SPA)
收听这些事件。
我会很感激任何帮助。
解决方案
我肯定会看看socketio-auth。
这个模块提供了在 socket.io 中实现身份验证的钩子,而不使用查询字符串来发送凭据,这不是一个好的安全实践。
我最近采用的另一种方法是使用JWT令牌 ( njwt ) 进行简单的基于令牌的身份验证。
我不想在 Node.js 中重新创建检查用户凭据的身份验证代码。(在我的情况下,它甚至无法连接到数据库)。相反,我会让使用套接字的 PHP 应用程序利用其已经建立的身份验证系统。使用套接字连接请求传递签名令牌。
您的 node.JS 代码可能看起来像...
primus.on('connection', function (spark) {
logger.debug('primus event connection. spark id: ' + spark.id);
spark.on('data', function(data) {
var action = data.action;
njwt.verify(data.token, JWT_SECRET, function(err, verifiedJwt) {
if (err) {
logger.warn('Bad JWT Token! ' + spark.id + ' Error: ' + err);
spark.user = {id:null, is_authed: false, is_admin: false, application_ini: null};
spark.end('Bad Token Request');
return; //->
}
spark.user = { 'id': verifiedJwt.body['user_id'],
'is_authed': verifiedJwt.body['is_authed'],
'application_ini': verifiedJwt.body['application_ini'],
'is_admin': verifiedJwt.body['is_admin']};
sockoasRooms.connect(spark.id, spark.user.application_ini, spark.user.id);
switch (action) {
...
然后在 PHP 方面,您需要一些代码来生成 JWT 令牌,但使用非常简单。就像是:
<?php
$tokenPayload = [ 'user_id' => ($this->currentUser) ? $this->currentUser->getId() : 0,
'is_authed' => ($this->currentUser) ? true : false,
'application_ini' => (string) APPLICATION_INI,
'is_admin' => (bool) ($this->currentUser) ? $this->currentUser->isAdministrator() : false,
'now' => time()
];
$jwtToken = \OAS_JWT::encode($tokenPayload, SOCK_OAS_JWT_KEY);
?>
$(document).ready(function() {
primus = Primus.connect('ws://<?=SOCK_OAS_IP?>:<?=SOCK_OAS_PORT?>/_admin');
primus.on('open', function () {
showConnected();
// Send request to subscribe
primus.write({action: 'dashboard-dump', token: '<?=$jwtToken?>'});
consoleWrite('Connected to dashboard.');
});
您可以评估时间分量以避免重放攻击。无论如何,听起来这种方法可能会满足您的需求。
题外话,但我也建议看看primus。它充当“实时框架的通用包装器”。这使您可以以某种方式抽象事物,以便您可以毫不费力地更换套接字库。可能比您使用的级别低一点(engine.IO)。
推荐阅读
- plperl - plperl; 找不到指定的模块 Postgres 10 - Windows 10 - Strawberry Perl 5.24
- c++ - 将函数添加到类中但避免重新编译
- javascript - 使用 createRef 聚焦子组件不起作用
- node.js - 无法使用 MEAN 堆栈连接到 Mongodb.atlas 集群
- c# - 无法让 Automapper 忽略属性
- github - 如何转义“#”,使其不会引用 GitHub 评论中的问题?
- ios - AVAsset(url: url).isPlayable 减慢集合视图
- html - Html CSS列表项目符号到图像不起作用
- java - API 'variant.getJavaCompile()' 已过时
- angular - Angular 表单控件不只更新 UI 的值