Подтвердить что ты не робот

Как различать роли/группы пользователей Symfony в каталоге socket.io

Я немного играл в чате socket.io, и у меня есть вопрос: как я могу различать пользователя администратора и обычного пользователя в комнате чата? Я бы хотел, чтобы администратор обладал такими полномочиями, как пинание и запрет людей, но моим пользователям это не нравится.

Я использую Symfony для разработки моего приложения, и я бы хотел использовать его пользовательскую базу данных для пользователей чата. Я использую FOSUserBundle для пользователей приложений Symfony. Они разделены на несколько групп, поэтому у меня есть группа admin и другие.

Группа admin имеет ROLE_ADMIN, что означает, что каждый пользователь внутри нее имеет эту роль. Это группа админов, и каждый пользователь этой группы должен иметь разрешения запрещать, удалять, отключать звук и т.д. Других пользователей в чате.

Для использования пользователей Symfony в чате я читал в Redis, чтобы получить их сеансы, но я не совсем уверен, как сделать разницу между пользователями admin и обычными пользователями. Как я могу запретить регулярному пользователю делать запрос на сервер, который делает то, к чему у пользователя нет доступа? Поскольку каждый может выполнять запросы, но , как я могу проверить эти запросы, если они поступают от пользователей, хранящихся в базе данных MySQL на сервере Apache?

Если не для Symfony, как это можно сделать в обычном PHP-приложении? В конце концов, не имеет значения, как определяется админ, но как подключить его к серверу Node и как заставить сервер Node работать с моей пользовательской базой данных.

У меня возникла идея просто зашифровать и отправить пользовательские данные на сервер Node, а затем расшифровать его там. Только два сервера знают секретные ключи, поэтому даже если клиент получает зашифрованные данные, он не может сделать запрос с ним для другого клиента. Я могу выполнить проверку IP и временную метку. Дешифрованные данные на сервере Node могут затем использоваться, чтобы сказать, является ли пользователь администратором или нет, и разрешить ему отправлять определенные запросы. Это хорошая идея или есть лучший способ?

4b9b3361

Ответ 1

У меня возникла идея просто зашифровать и отправить пользовательские данные на сервер node, а затем расшифровать его там. Только два сервера знают секретные ключи, поэтому даже если клиент получает зашифрованные данные, он не может сделать запрос с ним для другого клиента.

Это основная идея.

Как бы я это сделал? Я бы использовал что-то вроде JWT, чтобы просто отправить userId в приложение node. Не нужно зашифровывать, потому что я забочусь только о сигнатуре jwt, чтобы убедиться, что запрос действительно выдан реальным пользователем.

После этого, используя userId, я бы сделал вызов на стороне сервера в php-приложение для проверки ролей пользователя.

Разработать:

  • Приложение node и приложение php будут использовать общий секрет для подписывания токена JWT.
  • Приложение PHP выведет сгенерированный токен во внешний интерфейс.
  • Клиент socket.io отправит токен как часть аутентификации в приложение node.

Как обращаться с запретом

  • сохранить список открытых сокетов с их идентификатором пользователя
  • создайте конечную точку webservice в приложении nodejs, которая может hanlde "запретить" запросы из приложения php.
  • когда такой запрос принимается приложением nodejs, найдите сокет на основе идентификатора пользователя и закройте соединение.

Ответ 2

Я обычно создаю службу SecurityAccessManager для проверки ролей пользователей с помощью voters звонков (я могу предоставить пример, если необходимо), чтобы проверить конкретные права, такие как "этот пользователь может обновить эту конкретную запись?"

Config

company.navigation.security_access:
    class: Company\NavigationBundle\Services\SecurityAccessManager
    arguments: 
        - @security.authorization_checker            
        - @security.token_storage

Сервисный код

namespace Company\NavigationBundle\Services;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class SecurityAccessManager
{
    private $authorizationChecker;
    private $tokenStorage;
    private $debug;

    public function __construct(
            AuthorizationCheckerInterface $authorizationChecker,
            TokenStorage $tokenStorage)
    {      
        $this->authorizationChecker = $authorizationChecker;
        $this->tokenStorage = $tokenStorage;   
        $this->debug = true;
    }

    // *************************************************************************
    // User
    // *************************************************************************

    public function getUser()
    {
        return $this->tokenStorage->getToken()->getUser();        
    }

    public function getUserId()
    {
        return $this->tokenStorage->getToken()->getUser()->getId();        
    }

    public function isAuthenticatedUser()
    {    
       return $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED');
    }     

    // *************************************************************************
    // Roles checker
    // *************************************************************************

    public function isAdmin()
    {
        if($this->authorizationChecker->isGranted('ROLE_ADMIN') !== true) {
            return false;
        } else {
            return true;           
        }
    }    

    public function checkRightAdmin()
    {
        if($this->authorizationChecker->isGranted('ROLE_ADMIN') !== true) {
            throw new AccessDeniedException('Unauthorised access! '.($this->debug ? __FUNCTION__ : null));
        }

        return true;           
    }   

    public function checkUserHasRightToEditPost($postId)
    {
        // Check if user has right to modify the post
        if ($this->authorizationChecker->isGranted('is_user_has_right_to_edit_post', $postId) === false) {
            throw new AccessDeniedException('Unauthorised access! '.($this->debug ? __FUNCTION__ : null));
        }

        return true;
    }  
}

Затем в действиях ваших контроллеров вы можете проверить права пользователя

namespace Company\YourBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class YourBunbleController extends Controller
{   
    /**
     * Get the service
     * @return \Company\NavigationBundle\Services\SecurityAccessManager
     */
    private function getService()
    {        
        return $this->get('company.navigation.security_access');
    }  

    public function updatePostAction(Request $request, $postId)
    {   
        // Throw 403 if user has no admin rights
        $this->getService()->checkRightAdmin();

        // Throw 403 if user has no rights to update the post
        $this->getService()->checkUserHasRightToEditPost();

        //OK, you can update database
        ...
    }
}