Я следовал нескольким примерам из symfony, API-платформы и нескольким примерам stackoverflow, но безрезультатно. Я не знаю, то ли я делаю что-то не так, то ли я не понимаю концепции избирателя и ролей. Когда я пытался получить доступ к конечной точке, он выдает Только пользователь с правами доступа может просматривать панель инструментов.
В сервисах.yaml
app.user_permission:
class: App\Security\SecurityVoter
arguments: ['@security.access.decision_manager']
tags:
- { name: security.voter}
Я создал собственный избиратель для использования. Здесь я сделал несколько изменений, удалил несколько вещей, чтобы принять пример, который я видел в StackOverflow Пример.
use App\Entity\Product;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
class SecurityVoter extends Voter {
private $decisionManager;
const VIEW = 'view';
const EDIT = 'edit';
public function __construct (AccessDecisionManagerInterface $decisionManager) {
$this->decisionManager = $decisionManager;
}
protected function supports($attribute, $subject): bool {
// if the attribute isn't one we support, return false
if (!in_array($attribute, [self::VIEW, self::EDIT])) {
return false;
}
return true;
}
/**
* @param string $attribute
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($attribute, $object, TokenInterface $token): bool {
$user = $token->getUser();
if (!$user instanceof UserInterface) {
// the user must be logged in; if not, deny access
return false;
}
// check ROLE_USER
if ($this->security->isGranted('ROLE_USER')) {
return true;
}
switch ($attribute) {
case self::VIEW:
if ($this->decisionManager->decide($token, ['ROLE_USER'])) {
return true;
}
break;
case self::EDIT:
if ($this->decisionManager->decide($token, ['ROLE_USER'])) {
return true;
}
break;
}
throw new \LogicException('This code should not be reached!');
}
}
В моем Entity я определил что-то вроде этого.
#[ApiResource(
attributes: ["security" => "is_granted('ROLE_USER')"],
collectionOperations: [
"get",
"post" => [
"security_post_denormalize" => "is_granted('ROLE_USER)",
"security_message" => "Only user with permission can create a dashboard.",
],
],
itemOperations: [
"get" => [ "security" => "is_granted('VIEW') " , "security_message" => "Only user with permission can view dashboard."],
"put" => [ "security" => "is_granted('EDIT')", "security_message" => "Only user with permission can edit dashboard."],
],
)]
В настоящее время я использую Symfony 5.4.7, и я пытался использовать пример кода. Кажется, ничего не работает. Приходится использовать dd()
и dump()
, ни в консоли, ни в профилировщике ничего не печаталось. Я использовал loggerInterface
(возможно, я сделал это неправильно), и я не увидел, что что-то выводится в var.
Вы ближе, чем вы думаете. Вам не нужен используйте Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface. Вы можете использовать класс безопасности следующим образом.
use App\Entity\Product;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class SecurityVoter extends Voter {
private $security;
const VIEW = 'view';
const EDIT = 'edit';
public function __construct ( Security $security) {
$this->security = $security;
}
protected function supports($attribute, $subject): bool {
// if the attribute isn't one we support, return false
$supportsAttribute = in_array($attribute, ['VIEW', 'EDIT']);
$supportsSubject = $subject instanceof WorkshopSession;
return $supportsAttribute && $supportsSubject;
}
/**
* @param string $attribute
* @param Product $product
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool {
$user = $token->getUser();
if (!$user instanceof UserInterface) {
// the user must be logged in; if not, deny access
return false;
}
dd($user);
// check ROLE_USER
if ($this->security->isGranted('ROLE_USER')) {
return true;
}
switch ($attribute) {
case self::VIEW:
if ($this->security->isGranted('ROLE_USER')) {
return true;
}
break;
case self::EDIT:
if ($this->security->isGranted('ROLE_USER')) {
return true;
}
break;
}
throw new \LogicException('This code should not be reached!');
}
}
При этом вам не нужно настраивать сервис для этого.
Чтобы внедрить избиратель в уровень безопасности, вы должны объявить его как службу и пометить его с помощью security.voter. Но если вы используете конфигурацию services.yaml по умолчанию, это делается автоматически!
В вашей сущности
#[ApiResource(
attributes: ["security" => "is_granted('ROLE_USER')"],
collectionOperations: [
"get",
"post" => [
"security_post_denormalize" => "is_granted('ROLE_USER')",
"security_message" => "Only user with permission can create a dashboard.",
],
],
itemOperations: [
"get" => [ "security" => "is_granted('VIEW', object) " ],
"put" => [ "security" => "is_granted('EDIT')", "security_message" => "Only user with permission can edit dashboard."],
],
)]
Вы также можете прочитать это для справки - Платформа API
ПРИМЕЧАНИЕ: вы можете использовать dd() - например. дд ($ пользователь);