Авторизация для паспорта laravel через socket.io для каналов вещания - PullRequest
0 голосов
/ 30 апреля 2018

Я использую laravel 5.3 + паспорт для авторизации, Laravel - это мой внутренний API, который restful.

интерфейс написан на angular.js, который связывается с API с помощью запросов на отдых.

Для уведомлений в режиме реального времени я использовал laravel широковещательные события + redis и socket.io для сервера сокетов и клиента сокетов в angular.js.

Я хочу разрешить эти события, и я сделал это, насколько мог:

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, который запускает мой сервер сокетов:

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) для прослушивания этих событий.

Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 08 мая 2018

Я бы определенно взглянул на 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), чем то, что вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...