如何根据 FOSUserBundle 中的角色重定向到不同的路由?
How to redirect to different routes depending on role in FOSUserBundle?
我是 Symfony2 的新手,随后是 FOSUserBundle。我了解 bundle 是什么以及它的用途,但我对如何使用 bundle 与我已经存在的视图和控制器相关联有疑问。
我已经设置了捆绑包并使其正常工作,但我对下一个任务感到困惑。
设置:在 FOSUserBundle 的登录页面上,我希望 'admin users' 路由到某个页面,'normal users' 路由到另一个页面。我在哪里放置这个逻辑?我目前在我的包的 DefaultController 中有它但是得到页面:localhost isn't working...localhost redirected you too many times...
我清除了缓存但结果仍然相同。
默认控制器:
namespace Pas\ShopTestBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller
{
/**
* @Route("/")
* @Template()
*/
public function indexAction(Request $request) {
if ('admin_login' === $request->get('_route')) {
return $this->redirectToRoute('product'); //just test to product
} else {
return $this->redirectToRoute('login'); //just test to login
}
}
}
现在我的最终目标是一旦用户登录,他们的用户名就会显示在他们被发送到的页面上。我该如何编码?它去了哪里?
非常感谢大家的帮助,谢谢大家。
Symfony 2.7:FOSUserBundle 2.0
编辑:security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_ADMIN
ROLE_NORMAL: ROLE_NORMAL
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers:
fos_userbundle:
id: fos_user.user_provider.username
in_memory:
memory: ~
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: fos_user_security_check
provider: fos_userbundle
csrf_provider: form.csrf_provider
default_target_path: /
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
# - { path: ^/admin_login, role: ROLE_ADMIN }
问题来了。 indexAction 处的路由是 /
。您在 indexAction 中的条件基本上被解释为:"Does the current route, which is always /
because it is called from inside this route, equal to admin_login
?" 这就是为什么您的条件总是 returns false.
根据该逻辑,路由 /
总是重定向到路由 login
。路由 login
总是重定向到 /
因为登录角色是 IS_AUTHENTICATED_ANONYMOUSLY
但你已经通过身份验证(这意味着你当前的角色是 ROLE_NORMAL
或 ROLE_ADMIN
).
编辑:既然我读了你的评论更新,你只需要添加访问控制的路径:
access_control:
- { path: ^/$, role: ROLE_ADMIN }
- { path: ^/product$, role: ROLE_ADMIN }
并对 default/index 执行类似以下操作:
function indexAction() {
return $this->redirectToRoute('product');
}
EDIT2:如果您的 indexAction 除了重定向到路由 product
之外没有做任何事情,您可以删除控制器并将以下内容添加到 routing.yml:
root:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: product
permanent: true
或者你可以这样做:
将此添加到 security.yml 中的主防火墙
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
success_handler: acme_user.login_success_handler
logout: true
anonymous: true
并在 services.xml
中创建相应的服务
<services>
<service id="acme_user.login_success_handler" class="Acme\UserBundle\EventListener\LoginSuccessHandler">
<argument type="service" id="router" />
<argument type="service" id="security.context" />
<tag name="monolog.logger" channel="security"/>
</service>
</services>
然后 LoginSuccessHandler.php class:
<?php
namespace Acme\UserBundle\EventListener;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{
protected $router;
protected $security;
public function __construct(Router $router, SecurityContext $security)
{
$this->router = $router;
$this->security = $security;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
if ($this->security->isGranted('ROLE_SUPER_ADMIN') || $this->security->isGranted('ROLE_ADMIN')) {
$response = new RedirectResponse($this->router->generate('admin_route'));
} else {
$response = new RedirectResponse($this->router->generate('user_route'));
}
return $response;
}
}
我是 Symfony2 的新手,随后是 FOSUserBundle。我了解 bundle 是什么以及它的用途,但我对如何使用 bundle 与我已经存在的视图和控制器相关联有疑问。
我已经设置了捆绑包并使其正常工作,但我对下一个任务感到困惑。
设置:在 FOSUserBundle 的登录页面上,我希望 'admin users' 路由到某个页面,'normal users' 路由到另一个页面。我在哪里放置这个逻辑?我目前在我的包的 DefaultController 中有它但是得到页面:localhost isn't working...localhost redirected you too many times...
我清除了缓存但结果仍然相同。
默认控制器:
namespace Pas\ShopTestBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller
{
/**
* @Route("/")
* @Template()
*/
public function indexAction(Request $request) {
if ('admin_login' === $request->get('_route')) {
return $this->redirectToRoute('product'); //just test to product
} else {
return $this->redirectToRoute('login'); //just test to login
}
}
}
现在我的最终目标是一旦用户登录,他们的用户名就会显示在他们被发送到的页面上。我该如何编码?它去了哪里?
非常感谢大家的帮助,谢谢大家。
Symfony 2.7:FOSUserBundle 2.0
编辑:security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_ADMIN
ROLE_NORMAL: ROLE_NORMAL
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers:
fos_userbundle:
id: fos_user.user_provider.username
in_memory:
memory: ~
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: fos_user_security_check
provider: fos_userbundle
csrf_provider: form.csrf_provider
default_target_path: /
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
# - { path: ^/admin_login, role: ROLE_ADMIN }
问题来了。 indexAction 处的路由是 /
。您在 indexAction 中的条件基本上被解释为:"Does the current route, which is always /
because it is called from inside this route, equal to admin_login
?" 这就是为什么您的条件总是 returns false.
根据该逻辑,路由 /
总是重定向到路由 login
。路由 login
总是重定向到 /
因为登录角色是 IS_AUTHENTICATED_ANONYMOUSLY
但你已经通过身份验证(这意味着你当前的角色是 ROLE_NORMAL
或 ROLE_ADMIN
).
编辑:既然我读了你的评论更新,你只需要添加访问控制的路径:
access_control:
- { path: ^/$, role: ROLE_ADMIN }
- { path: ^/product$, role: ROLE_ADMIN }
并对 default/index 执行类似以下操作:
function indexAction() {
return $this->redirectToRoute('product');
}
EDIT2:如果您的 indexAction 除了重定向到路由 product
之外没有做任何事情,您可以删除控制器并将以下内容添加到 routing.yml:
root:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: product
permanent: true
或者你可以这样做:
将此添加到 security.yml 中的主防火墙
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
success_handler: acme_user.login_success_handler
logout: true
anonymous: true
并在 services.xml
中创建相应的服务<services>
<service id="acme_user.login_success_handler" class="Acme\UserBundle\EventListener\LoginSuccessHandler">
<argument type="service" id="router" />
<argument type="service" id="security.context" />
<tag name="monolog.logger" channel="security"/>
</service>
</services>
然后 LoginSuccessHandler.php class:
<?php
namespace Acme\UserBundle\EventListener;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{
protected $router;
protected $security;
public function __construct(Router $router, SecurityContext $security)
{
$this->router = $router;
$this->security = $security;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
if ($this->security->isGranted('ROLE_SUPER_ADMIN') || $this->security->isGranted('ROLE_ADMIN')) {
$response = new RedirectResponse($this->router->generate('admin_route'));
} else {
$response = new RedirectResponse($this->router->generate('user_route'));
}
return $response;
}
}