通过socket.io授权laravel护照用于广播频道 [英] Authorization for laravel passport through socket.io for broadcasting channels

查看:160
本文介绍了通过socket.io授权laravel护照用于广播频道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用laravel 5.3 +护照进行授权,Laravel是我的后端API,即restful.

I'm using laravel 5.3 + passport for authorization, Laravel is my back-end API which is restful.

前端是用angular.js编写的,它与具有其余请求的API进行通信.

front-end is written in angular.js which communicate with API with rest requests.

对于实时通知,我已经将laravel广播事件+ redissocket.io用于angular.js.

For Real-time notifications, I've used laravel broadcasting events + redis, and socket.io for socket server and socket client in angular.js.

我想授权这些事件,并且已经尽我所能:

I want to authorize these events and I've done it far as I could :

BroadcastServiceProvider:

BroadcastServiceProvider :

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代码:

This is my socket.js code which runs my socket server :

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)中的用户收听这些事件.

The problem is I don't know how to authenticate these broadcasting events in socket server and also how to authorize the user in angular.js (SPA) to listen to these events.

我将不胜感激.

推荐答案

我肯定会看一下

此模块提供钩子以在socket.io中实现身份验证 没有使用查询字符串发送凭据,这不是一个好习惯 安全实践.

This module provides hooks to implement authentication in socket.io without using querystrings to send credentials, which is not a good security practice.

我最近采取的另一种方法是使用 JWT 令牌( njwt ).

Another approach I took recently was simple token based authentication using JWT tokens (njwt).

我不想重新创建用于检查Node.js中用户凭证的身份验证代码. (就我而言,它甚至无法连接到数据库).相反,我会让正在使用套接字的PHP应用程序利用其已经建立的身份验证系统.通过套接字连接请求传递签名令牌.

I did not want to recreate the authentication code that checks user credentials within Node.js. (which in my case can't even connect to the database anyway). Rather, I'd let the PHP application that was using the socket leverage its already established authentication system. Passing a signed token with the socket connect requests.

您的node.JS代码可能类似于...

Your node.JS code might look something like...

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令牌的代码,但使用非常简单.像这样:

And then on the PHP side, you'll need some code for generating the JWT tokens, but use is very simple. Something like:

<?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.');
    });

您可以评估时间部分,以避免重放攻击.无论如何,听起来像这种方法可能会满足您的需求.

You can evaluate the time component to avoid replay attacks. Anyway, sounds like this approach might meet your needs.

主题外,但我还建议您查看 primus .它充当实时框架的通用包装".这使您可以某种方式抽象事物,从而可以轻松地换出套接字库.可能会比您使用的级别低一些(engine.IO).

Off topic but I'd also suggest taking a look at primus. It acts as a "universal wrapper for real-time frameworks". This lets you abstract things in a way so you could swap out the socket libraries with no hassle. Might be a little lower level (engine.IO) than what you are using though.

这篇关于通过socket.io授权laravel护照用于广播频道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆