我可以在 symfony 中创建类似于 isGranted 的东西吗?
Can I create something similar to isGranted in symfony?
所以基本上我想创建类似 @IsGranted
的东西。
例如,我在我的应用程序上使用了 @IsGranted
来访问控制,以防止简单用户访问管理页面。
在我的实体上,我有一个名为 is_Active
的布尔字段
- 如果为真 (1),则用户可以使用他的帐户
- 如果为假 (0),他将被重定向到错误页面!
在这种情况下,我不会在用户的 Roles
字段上进行测试,但我会在 is_Active
字段上进行测试 这就是为什么 我不能使用 @IsGranted
.
我创建了一个错误的 twig 页面 active.html.twig
我把它放在模板文件夹中,我发现自己被迫在 每个 控制器函数上添加这两行。
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
的东西并将其用在每个函数的注释上?
我会为此使用身份验证,这样你就不必触摸你的控制器了。您可以检查他们是否已登录并处于活动状态,然后他们可以查看内容,或者如果他们未通过身份验证,则您可以使用 active.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
您可以继续对自定义选民使用@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')")
所以基本上我想创建类似 @IsGranted
的东西。
例如,我在我的应用程序上使用了 @IsGranted
来访问控制,以防止简单用户访问管理页面。
在我的实体上,我有一个名为 is_Active
- 如果为真 (1),则用户可以使用他的帐户
- 如果为假 (0),他将被重定向到错误页面!
在这种情况下,我不会在用户的 Roles
字段上进行测试,但我会在 is_Active
字段上进行测试 这就是为什么 我不能使用 @IsGranted
.
我创建了一个错误的 twig 页面 active.html.twig
我把它放在模板文件夹中,我发现自己被迫在 每个 控制器函数上添加这两行。
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
的东西并将其用在每个函数的注释上?
我会为此使用身份验证,这样你就不必触摸你的控制器了。您可以检查他们是否已登录并处于活动状态,然后他们可以查看内容,或者如果他们未通过身份验证,则您可以使用 active.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
您可以继续对自定义选民使用@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')")