【问题标题】:How to redirect to different routes depending on role in FOSUserBundle?如何根据 FOSUserBundle 中的角色重定向到不同的路由?
【发布时间】:2016-03-16 19:36:22
【问题描述】:

我是 Symfony2 和 FOSUserBundle 的新手。我了解捆绑包是什么以及将其用于什么用途,但我对如何使用捆绑包与我已经到位的视图和控制器相关联有疑问。

我已经设置了捆绑包并使其正常工作,但我对下一个任务感到困惑。

设置:在 FOSUserBundle 的登录页面上,我希望将“管理员用户”路由到某个页面,而将“普通用户”路由到另一个页面。我在哪里放置这个逻辑?我目前在我的捆绑包的 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 }

【问题讨论】:

  • 什么是普通用户?它是经过身份验证的用户还是只是一个匿名用户?什么是'admin_login'?为什么要在default/index 中测试“admin_login”路由?你能给我们提供security.yml,特别是关于访问控制的吗?我认为您的重定向发生是因为您已经登录,因此该应用程序将您重定向到 default/index 并且您的条件从未满足('admin_login' != _route),因此它将其重定向回登录。这会永远循环下去,最终会给你带来太多的重定向。
  • 我使用 security.yml 进行了编辑。普通用户是经过身份验证的匿名用户。我也明白你的意思...我还应该在哪里/应该测试 admin_login?

标签: php symfony fosuserbundle


【解决方案1】:

或者你可以这样做:

将它添加到 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 类:

<?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;
    }
}

【讨论】:

    【解决方案2】:

    这就是问题所在。 indexAction 处的路由是/。您在 indexAction 中的条件基本上被解释为:“当前路由是否始终为/,因为它是从该路由内部调用的,等于admin_login?”这就是为什么你的条件总是返回 false。

    使用该逻辑,路由/ 总是重定向到路由login。并且路由login 总是重定向到/,因为登录角色是IS_AUTHENTICATED_ANONYMOUSLY,但您已经通过身份验证(这意味着您当前的角色是ROLE_NORMALROLE_ADMIN)。

    编辑:现在我阅读了您的评论更新,您只需要添加访问控制的路径:

    access_control:
        - { path: ^/$, role: ROLE_ADMIN }
        - { path: ^/product$, role: ROLE_ADMIN }
    

    并对默认/索引执行以下操作:

    function indexAction() {
        return $this->redirectToRoute('product');
    }
    

    EDIT2:如果您的 indexAction 除了重定向到路由 product 之外没有做任何事情,您可以移除控制器并将以下内容添加到 routing.yml:

    root:
        path: /
        defaults:
            _controller: FrameworkBundle:Redirect:redirect
            route: product
            permanent: true
    

    Source

    【讨论】:

    • 啊完美,非常感谢!问你是否也能帮助我解决我的“最终目标”问题会不会太过分了?我对如何让这个包与我的其他控制器和视图交互感到困惑(我没有通过文档找到任何好的东西)
    • 查看SecurityFOSUserBundle 的文档。将 FOSUserBundle 视为 symfony 用户管理器的后端。仅当您需要创建用户、通过 id 查找用户等时才使用捆绑包,同时使用安全性来授权用户的角色、获取当前登录的用户等。
    猜你喜欢
    • 1970-01-01
    • 2015-09-09
    • 2021-07-12
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多