FOSUserBundle - 如何在尝试访问login_path时重定向已登录的用户

Ang*_*edi 4 php security firewall symfony fosuserbundle

是否可以/login仅为用户执行自动重定向到特定路由的某个路由(即/)AUTHENTICATED?如何?

我正在使用FOSUserBundle.

这是我的安全配置:

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN

providers:
    fos_userbundle:
        id: fos_user.user_provider.username_email

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_provider: form.csrf_provider
            login_path: /accedi
            check_path: /login_check
            default_target_path: /
        oauth:
            resource_owners:
                facebook:           "/login/check-facebook"
                google:             "/login/check-google"
            login_path:        /accedi
            failure_path:      /accedi
            default_target_path: /

            oauth_user_provider:
                service: my_user_provider
        logout:
            path: /logout
            target: /
            invalidate_session: false
        anonymous:  ~
    login:
        pattern:  ^/login$
        security: false

        remember_me:
            key: "%secret%"
            lifetime: 31536000 # 365 days in seconds
            path: /
            domain: ~ 

    oauth_authorize:
        pattern:    ^/oauth/v2/auth
        form_login:
            provider: fos_userbundle
            check_path: _security_check
            login_path: _demo_login
        anonymous: true

    oauth_token:
        pattern:    ^/oauth/v2/token
        security:   false


access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/accedi$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/registrati, role: IS_AUTHENTICATED_ANONYMOUSLY }
Run Code Online (Sandbox Code Playgroud)

Nic*_*ich 11

当您使用FOSUserBundle时,登录表单的呈现将在SecurityController::renderLogin().

解决方案基本上是:

  • 覆盖SecurityController
  • 添加对角色的检查 IS_AUTHENTICATD_ANONYMOUSLY
  • 如果找不到该角色,则将用户重定向到另一个页面

我假设您已经创建了一个扩展FOSUserBundle的包,它保存您的User实体.

我假设这个包被调用YourUserBundle并位于src/Your/Bundle/UserBundle.

现在复制(不切割)SecurityController

vendor/friendsofsymfony/user-bundle/src/FOS/UserBundle/Controller/SecurityController.php
Run Code Online (Sandbox Code Playgroud)

to(为了覆盖FOSUserBundle提供的那个)

src/Your/Bundle/UserBundle/Controller/SecurityController.php
Run Code Online (Sandbox Code Playgroud)

添加use-statement RedirectResponse并编辑renderLogin()方法,如下所示:

use Symfony\Component\HttpFoundation\RedirectResponse;

// ...

protected function renderLogin(array $data)
{
    if (false === $this->container->get('security.context')->isGranted('IS_AUTHENTICATED_ANONYMOUSLY')) {
        return new RedirectResponse('/', 403);
    }

    $template = sprintf('FOSUserBundle:Security:login.html.%s', $this->container->getParameter('fos_user.template.engine'));

    return $this->container->get('templating')->renderResponse($template, $data);
}
Run Code Online (Sandbox Code Playgroud)

更新

现在而不是security.context使用security.authorization_checker.

http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements


小智 7

在我看来,覆盖登录表单的呈现是在错误的地方提供答案.登录表单的呈现不是负责登录的表单.这是登录请求的结果.它可能在未来的其他地方有其他用法,你将破坏这些情况的功能.

覆盖登录操作对我来说似乎更好.这是负责处理登录请求的实际组件.

为此,请覆盖安全控制器中的登录操作.假设您的MyProject项目中有MyUserBundle,它扩展了FOSUserBundle.

<?php

namespace MyProject\MyUserBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\SecurityController as BaseSecurityController;

class SecurityController extends BaseSecurityController
{

    /**
     * Overriding login to add custom logic.
     */
    public function loginAction(Request $request)
    {
        if( $this->container->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED') ){

            // IS_AUTHENTICATED_FULLY also implies IS_AUTHENTICATED_REMEMBERED, but IS_AUTHENTICATED_ANONYMOUSLY doesn't

            return new RedirectResponse($this->container->get('router')->generate('some_route_name_in_my_project', array())); 
            // of course you don't have to use the router to generate a route if you want to hard code a route
        }

        return parent::loginAction($request);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 只需使用$ this-> container-> get('security.authorization_checker')代替(2.6中的新功能) (2认同)