我在食谱中读到这一章后
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);
答案 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()));
}
}
非常简单。我更喜欢过滤器变体。