Могу ли я создать что-то похожее на isGranted в symfony? - PullRequest
1 голос
/ 20 июня 2020

Итак, я хочу создать что-то вроде @IsGranted. Я использовал @IsGranted в своем приложении для контроля доступа, например, чтобы предотвратить доступ простого пользователя к странице администратора.

В моей сущности у меня есть логическое поле с именем is_Active

  • если это правда (1), то пользователь может использовать свою учетную запись
  • , если ложь (0), тогда он будет перенаправлен на страницу с ошибкой!

В этом случае я я не собираюсь тестировать поле Roles пользователя, но я собираюсь протестировать поле is_Active , поэтому я не могу использовать @IsGranted.

I создал страницу ветки ошибки active.html.twig, и я помещаю ее в папку шаблонов, и я обнаружил, что ПРИНУДИТЕЛЬНО добавить эти 2 строки в каждую функцию контроллера.

if ($this->getUser()->getIsActive()==false) {
     return $this->render('active.html.twig');}

Вот пример :

/**
 * @IsGranted("ROLE_ADMIN")
 * @Route("/", name="user_index", methods={"GET"})
 */
public function index(UserRepository $userRepository): Response
{
    if ($this->getUser()->getIsActive()==false) {
        return $this->render('active.html.twig');}
            
    return $this->render('user/index.html.twig', [
        'users' => $userRepository->findAll(),
    ]);
}

Это очень тяжело и плохо - добавлять этот оператор if для каждой функции (у меня +30 функций в приложении)

Может быть, я смогу создать что-то похожее на @IsGranted и использовать его вместо аннотации каждой функции?

Ответы [ 2 ]

2 голосов
/ 01 июля 2020

Вы можете продолжать использовать @IsGranted с настраиваемым избирателем. https://symfony.com/doc/current/security/voters.html#creating -the-custom-voter

Создайте нового избирателя, как в документации

public const ACTIVE = 'active';

protected function supports(string $attribute, $subject)
{
    return $attribute === self::ACTIVE;
}

protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
{
    $user = $token->getUser();

    if ($user instanceof User && !$user->isActive()) {
        throw new InactiveUserException();
    }

    return true;
}

Затем вы можете создать слушателя для InactiveUserException и показать, что если вы хотите, чтобы клиент.

В вашем контроллере вам нужно будет поставить @IsGranted("active") или @Security(expression="is_granted('active')") перед методом маршрута или контроллером

1 голос
/ 20 июня 2020

Я бы использовал аутентификацию для этого, тогда вам не нужно прикасаться к своим контроллерам. Вы можете проверить, вошли ли они в систему и активны ли они, затем они могут просматривать контент или, если они не проходят аутентификацию, вы можете направить их по другому маршруту с вашим активным. html .twig.

Вы также можете просто этот набор на определенных маршрутах или на всех из них.

https://symfony.com/doc/current/security/guard_authentication.html

Образец аутентификатора и установите его только для ваших маршрутов администратора, тогда вы можете иметь обычный аутентификатор без проверки для активного пользователя на checkCredentials для всех остальных маршрутов.

<?php

namespace App\Security;

use App\Entity\User;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Twig\Environment;

class AdminAuthenticator extends AbstractGuardAuthenticator
{
    /** @var Environment */
    private $twig;

    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }

    public function supports(Request $request): bool
    {
        $email = $request->request->get('email');
        $password = $request->request->get('password');

        return $email && $password;
    }

    public function getCredentials(Request $request)
    {
        $email = $request->request->get('email');
        $password = $request->request->get('password');

        return [
            'email' => $email,
            'password' => $password
        ];
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $email = $credentials['email'];
        return $userProvider->loadUserByUsername($email);
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        $password = $credentials['password'];
        if (!$this->passwordEncoder->isPasswordValid($user, $password)) {
            throw new CustomUserMessageAuthenticationException(
                'Sorry, you\'ve entered an invalid username or password.'
            );
        }
        
        if (!$user->isActive()) {
            throw new NotActiveUserException(
                'This account is not active'
            );
        }

        return true;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        if ($exception instanceof NotActiveUserException) {

            // You should redirect here but you get the idea!
            $this->twig->render('active.html.twig');
        }
        
        // Do something else for any other failed auth
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        return new JsonResponse('success', Response::HTTP_OK);
    }

    public function start(Request $request, AuthenticationException $authException = null)
    {
        return new JsonResponse('Not Authorized', Response::HTTP_UNAUTHORIZED);
    }

    public function supportsRememberMe()
    {
        return false;
    }
}

Затем в вашем security.yaml

    firewalls:
        admin:
            pattern: ^/admin
            provider: user
            guard:
                authenticators:
                    - App\Security\AdminAuthenticator
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...