【问题标题】:How to differentiate between Symfony user roles/groups in socket.io chat如何区分 socket.io 聊天中的 Symfony 用户角色/组
【发布时间】:2016-01-17 02:45:54
【问题描述】:

我一直在玩socket.io的聊天,我有一个问题:我如何区分聊天室中的管理员用户和普通用户?我希望管理员拥有像踢人和禁止人这样的权力,但我的用户没有。

我正在使用 Symfony 开发我的应用程序,我想将其用户数据库用于聊天用户。我正在为我的 Symfony 应用程序的用户使用FOSUserBundle。它们被分成多个组,所以我有admin 组和其他组。

admin 组具有ROLE_ADMIN,这意味着其中的每个用户都具有该角色。即管理员组,该组中的每个用户都应有权禁止、踢出、静音等聊天室中的其他用户。

为了在聊天中使用我的 Symfony 用户,我一直在阅读 Redis 以获取他们的会话,但我不确定如何区分我的管理员用户和普通用户。如何防止普通用户向服务器发出用户无权访问的请求?因为任何人都可以发出请求,但是如果这些请求来自存储在 Apache 服务器上的 MySQL 数据库中的用户,我如何验证这些请求?

如果不是 Symfony,如何在普通的 PHP 应用程序中做到这一点?最后,admin如何定义并不重要,重要的是如何将他连接到Node服务器以及如何使Node服务器与我的用户数据库一起工作。

我的想法是简单地加密用户数据并将其发送到节点服务器,然后在那里解密。只有两台服务器知道私钥,因此即使客户端获得加密数据,他也无法向另一个客户端发出请求。我可能会做一些 IP 检查和时间戳。然后可以使用节点服务器上的解密数据来判断用户是否是管理员,并允许他发送某些请求。这是个好主意还是有更好的方法?

【问题讨论】:

标签: php node.js sockets symfony socket.io


【解决方案1】:

我的想法是简单地加密用户数据并将其发送到节点服务器,然后在那里解密。只有两台服务器知道私钥,因此即使客户端获得了加密数据,他也无法向另一个客户端发出请求。

这是基本的想法。

我会怎么做? 我会使用 JWT 之类的东西将 userId 发送到节点应用程序。不必加密,因为我只关心 jwt 签名以确保请求确实是由真实用户发出的。

之后,使用 userId 我会服务器端调用 php 应用程序来检查用户的角色。

详细说明:

  • node 应用和 php 应用将使用共享密钥来签署 JWT 令牌。
  • PHP 应用程序会将生成的令牌公开给前端。
  • socket.io 客户端会将令牌作为身份验证的一部分发送到节点应用程序。

如何处理禁令

  • 保留打开的套接字列表及其用户 ID
  • 在 nodejs 应用程序中创建一个 Web 服务端点,它可以处理来自 php 应用程序的“禁止”请求。
  • 当nodejs应用收到这样的请求时,根据userid查找socket并关闭连接。

【讨论】:

  • 是的,我们发现使用 WebToken 是可行的方法。
【解决方案2】:

我通常创建一个SecurityAccessManager 服务来通过voters 调用检查用户的角色(如果需要,我可以提供一个示例)来检查特定的权限,例如“这个用户可以更新这个特定的帖子吗?”

配置

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
        ...
    }
}

【讨论】:

  • 这是一个格式非常正确的答案,但它并没有解决我的问题。我已经做了一个voter来检查权限,我也可以检查用户ROLE,也可以检查组。我的问题是如何将这些角色传递给 node.js 服务器,因此它可以控制聊天室。以及如何在节点和我的 mysql 数据库上拥有相同的用户。例如,管理员如何禁止某些用户访问?
  • 禁止也应该立即关闭套接字连接,因此节点必须与数据库有某种关系并与 Symfony 应用程序并行工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
  • 2020-01-18
  • 1970-01-01
  • 2015-07-20
  • 2018-08-12
  • 2014-02-10
  • 2015-11-09
相关资源
最近更新 更多