被授予其他用户

时间:2015-06-30 14:20:44

标签: symfony

我在食谱中读到这一章后

http://symfony.com/doc/current/cookbook/security/entity_provider.html

我创建了一个实体" User"它实现了" AdvancedUserInterface"和一个实体"角色"它实现了" RoleInterface"。我还在我的" security.yml"。

中创建了一个角色结构

用户和角色之间的关系是" ManyToMany"关系。

一切都很好。

对于登录用户,我可以查看这样的拨款:

$this->get('security.context')->isGranted("ROLE_EDITOR");

但是如何在数据库中为其他用户检查此授权?

有类似的东西吗?

$this->get('security.context')->isGranted("ROLE_EDITOR", $user);

3 个答案:

答案 0 :(得分:2)

Symfony 5 答案:

namespace App\Controller;

...
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

class UserController extends AbstractController
{
    private $roleHierarchy;

    /**
     * @Route("/users", name="users")
     */
    public function usersIndex(RoleHierarchyInterface $roleHierarchy)
    {
        $this->roleHierarchy = $roleHierarchy;

        // your user service or your Doctrine code here
        $users = ...

        foreach ($users as $user) {
            $roles = $roleHierarchy->getReachableRoleNames($user->getRoles());
            \dump($roles);

            if ($this->isGranted($user, 'ROLE_SUPER_ADMIN')) {
                ...
            }
        }
        ...
    }

    private function isGranted(User $user, string $role): bool 
    {
        $reachableRoles = $this->roleHierarchy->getReachableRoleNames($user->getRoles());

        foreach ($reachableRoles as $reachableRole) {
            if ($reachableRole === $role) {
                return true;
            }
        }

        return false;
    }
}

注意:为了简化起见,我将所有内容都放在了控制器中,但是我当然建议将角色管理代码移到单独的服务中,例如@leberknecht的答案。

答案 1 :(得分:0)

不知道现在是否有内置的东西,但是它很简单直接构建:

class RoleCheckerService
{
    private const PROVIDER_KEY = 'role-check';
    /**
     * @var RoleHierarchyInterface
     */
    private $roleHierarchy;

    public function __construct(RoleHierarchyInterface $roleHierarchy)
    {
        $this->roleHierarchy = $roleHierarchy;
    }

    final public function isGranted(User $user, string $role): bool 
    {
        $token = new PreAuthenticatedToken($user, null, self::PROVIDER_KEY, $user->getRoles());
        $reachableRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());

        foreach ($reachableRoles as $reachableRole) {
            if ($reachableRole->getRole() === $role) {
                return true;
            }
        }

        return false;
    }
}

答案 2 :(得分:0)

在 PHP 代码中,我只是注入了 RoleHierarchyInterface 并使用了这个简单的表达式:

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>

int main(int argc, char** argv)
{
    char password[1024]; // Increased buffer size
    int len;
    int i;
    
    bool has_upper = false, has_lower = false, has_num = false; // To check each requirement
    printf("Please enter Password: ");
    fgets(password, sizeof password, stdin); // Safer than scanf
    len = strlen(password); // Take length after input
    for (i = 0; i < len; i++) // i <= len - 1 is a bit redundant, i < len is better
    {
        if (isupper(password[i]))
            has_upper = true;
        else if (islower(password[i]))
            has_lower = true;
        else if (isdigit(password[i]))
            has_num = true;
    }
    if(has_upper && has_lower && has_num)
        printf("Done\n");
    else
        printf("Wrong\n");
}

在 Twig 中,我编写了这个简单的扩展程序(适用于当前版本:Symfony 5.2 和 Twig 3.3):

if (in_array($role, $this->roleHierarchy->getReachableRoleNames($user->getRoles()))) {
  // whatever
}

<?php
// /src/Twig/AccessCheckExtension.php
declare(strict_types=1);
namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class AccessCheckExtension extends AbstractExtension
{
    public function getFilters(): array
    {
        return [
            new TwigFilter('has_role', [AccessCheckRuntime::class, 'hasRole'])
        ];
    }
    
    public function getFunctions(): array
    {
        return [
            new TwigFunction('has_role', [AccessCheckRuntime::class, 'hasRole'])
        ];
    }
}

这可以在 Twig 模板中使用,如下所示:

<?php
// /src/Twig/AccessCheckRuntime.php
declare(strict_types=1);
namespace App\Twig;

use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Twig\Extension\RuntimeExtensionInterface;

class AccessCheckRuntime implements RuntimeExtensionInterface
{
    /**
     * this uses PHP 8.0 constructor property promotion to reduce the needed lines
     **/
    public function __construct(
        protected RoleHierarchyInterface $roleHierarchy
    ){}

    public function hasRole(UserInterface $user, string $role): bool
    {
        return in_array($role, $this->roleHierarchy->getReachableRoleNames($user->getRoles()));
    }
}

非常简单。我更喜欢过滤器变体。