[英]How to redirect to different url based on roles in symfony 2
我在網站上有一個登錄頁面。 我有 4 個不同的用戶類型,我希望當他們登錄時,他們會根據分配的角色轉到不同的頁面。
有什么辦法嗎?
解決此問題的一種方法是在security.interactive_login
事件上使用事件偵聽器。 在這種情況下,我只是在該事件監聽器中附加另一個監聽器,因此它將觸發響應。 這樣可以使身份驗證仍然發生,但仍然可以在完成后執行重定向。
<service id="sotb_core.listener.login" class="SOTB\CoreBundle\EventListener\SecurityListener" scope="request">
<tag name="kernel.event_listener" event="security.interactive_login" method="onSecurityInteractiveLogin"/>
<argument type="service" id="router"/>
<argument type="service" id="security.context"/>
<argument type="service" id="event_dispatcher"/>
</service>
而班級......
class SecurityListener
{
protected $router;
protected $security;
protected $dispatcher;
public function __construct(Router $router, SecurityContext $security, EventDispatcher $dispatcher)
{
$this->router = $router;
$this->security = $security;
$this->dispatcher = $dispatcher;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
}
public function onKernelResponse(FilterResponseEvent $event)
{
if ($this->security->isGranted('ROLE_TEAM')) {
$response = new RedirectResponse($this->router->generate('team_homepage'));
} elseif ($this->security->isGranted('ROLE_VENDOR')) {
$response = new RedirectResponse($this->router->generate('vendor_homepage'));
} else {
$response = new RedirectResponse($this->router->generate('homepage'));
}
$event->setResponse($response);
}
}
對於Symfony> = 2.6現在將是:
<?php
namespace CommonBundle\Listener;
use Monolog\Logger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class LoginListener
{
/** @var Router */
protected $router;
/** @var TokenStorage */
protected $token;
/** @var EventDispatcherInterface */
protected $dispatcher;
/** @var Logger */
protected $logger;
/**
* @param Router $router
* @param TokenStorage $token
* @param EventDispatcherInterface $dispatcher
* @param Logger $logger
*/
public function __construct(Router $router, TokenStorage $token, EventDispatcherInterface $dispatcher, Logger $logger)
{
$this->router = $router;
$this->token = $token;
$this->dispatcher = $dispatcher;
$this->logger = $logger;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
}
public function onKernelResponse(FilterResponseEvent $event)
{
$roles = $this->token->getToken()->getRoles();
$rolesTab = array_map(function($role){
return $role->getRole();
}, $roles);
$this->logger->info(var_export($rolesTab, true));
if (in_array('ROLE_ADMIN', $rolesTab) || in_array('ROLE_SUPER_ADMIN', $rolesTab)) {
$route = $this->router->generate('backend_homepage');
} elseif (in_array('ROLE_CLIENT', $rolesTab)) {
$route = $this->router->generate('frontend_homepage');
} else {
$route = $this->router->generate('portal_homepage');
}
$event->getResponse()->headers->set('Location', $route);
}
}
和services.yml
services:
common.listener.login:
class: CommonBundle\Listener\LoginListener
arguments: [@router, @security.token_storage, @event_dispatcher, @logger]
scope: request
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
在Symfony 3.1中測試
您還可以在用戶成功登錄security.yml文件中的所有用戶后設置默認路徑,如下所示:
[配置/ security.yml]
...
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: /.*
form_login:
login_path: /login
check_path: /login_check
default_target_path: /login/redirect <<<<<<<<<<<<<<<<<<<<<<<<<
logout:
path: /logout
target: /
security: true
anonymous: ~
...
然后在default_target_path
方法中根據用戶角色進行簡單的重定向。 很直接。 有人說最簡單的方法總是最好的方式。 你決定 :)
[SomeBundle /控制器/ SomeController.php]
/**
* Redirect users after login based on the granted ROLE
* @Route("/login/redirect", name="_login_redirect")
*/
public function loginRedirectAction(Request $request)
{
if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY'))
{
return $this->redirectToRoute('_login');
// throw $this->createAccessDeniedException();
}
if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN'))
{
return $this->redirectToRoute('_admin_panel');
}
else if($this->get('security.authorization_checker')->isGranted('ROLE_USER'))
{
return $this->redirectToRoute('_user_panel');
}
else
{
return $this->redirectToRoute('_login');
}
}
像魅力一樣工作,但請記住,如果您的ROLE_ADMIN還具有ROLE_USER等權限,則始終向下檢查大多數受限制的角色......
我使用了Mdrollette的答案,但這個解決方案有一個很大的缺點,你完全覆蓋了symfony原始的響應,並通過這樣做刪除了由symfony在標題中設置的記住我的cookie。
我的解決方案是以這種方式更改OnKernelResponse:
public function onKernelResponse(FilterResponseEvent $event)
{
if ($this->security->isGranted('ROLE_TEAM')) {
$event->getResponse()->headers->set('Location', $this->router->generate('team_homepage'));
} elseif ($this->security->isGranted('ROLE_VENDOR')) {
$event->getResponse()->headers->set('Location', $this->router->generate('vendor_homepage'));
} else {
$event->getResponse()->headers->set('Location', $this->router->generate('homepage'));
}
}
這樣你就可以保持完整記住我的cookie。
如果您正在尋找比@MDrollette更簡單的答案,您可以將類似的重定向塊放入登錄成功頁面的控制器中。
為了測試,如果您想要保留原始響應,您也可以只復制標題。 Redirect對象上的clone方法僅復制標頭。
public function onKernelResponse(FilterResponseEvent $event)
{
if ($this->security->isGranted('ROLE_TEAM')) {
$response = new RedirectResponse($this->router->generate('team_homepage'));
} elseif ($this->security->isGranted('ROLE_VENDOR')) {
$response = new RedirectResponse($this->router->generate('vendor_homepage'));
} else {
$response = new RedirectResponse($this->router->generate('homepage'));
}
$response->headers = $response->headers + $event->getResponse()->headers;
$event->setResponse($response);
}
我在登錄表單身份驗證器中使用它根據角色重定向用戶(symfony:4.26.8):
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
private $urlGenerator;
/**
* @var Security
*/
private $security;
public function __construct(UrlGeneratorInterface $urlGenerator ,Security $security)
{
$this->urlGenerator = $urlGenerator;
$this->security = $security;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// redirecting user by role :
$user = $this->security->getUser();
$roles = $user->getRoles();
$rolesTab = array_map(function($role){
return $role;
}, $roles);
if (in_array('ROLE_ADMIN', $rolesTab) || in_array('ROLE_SUPER_ADMIN', $rolesTab)) {
return new RedirectResponse($this->urlGenerator->generate('admin'));
}
else{
return new RedirectResponse($this->urlGenerator->generate('home'));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.