Symfony 如何在侦听器中进行重定向

Symfony 如何在侦听器中进行重定向,symfony,Symfony,我试图在侦听器中进行重定向,但它不起作用 我的听众: <?php // AuthenticationListener.php namespace Acme\UserBundle\Listener; use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony

我试图在侦听器中进行重定向,但它不起作用

我的听众:

<?php
// AuthenticationListener.php

namespace Acme\UserBundle\Listener;

use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;

class AuthenticationListener
{
    protected $router;

    public function __construct(Router $router)
    {
        $this->router = $router;
    }

    public function onAuthenticationFailure(AuthenticationFailureEvent $event)
    {
        if(preg_match("/m\/login/", $_SERVER['HTTP_REFERER'])){
            // var_dump('Hello'); die();
            return new RedirectResponse($this->router->generate('mobile_login'));
        }
    }

    public function onAuthenticationSuccess(InteractiveLoginEvent $event)
    {
        if(preg_match("/m\/login/", $_SERVER['HTTP_REFERER'])){
           return new RedirectResponse($this->router->generate('mobile_home'));
        }
    }
}
My UserBundle/[…]/routing.yml

mobile_login:
    pattern:  /m/login
    defaults: { _controller: AcmeUserBundle:Mobile:login }
编辑Abdallah Arffak

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

    role_hierarchy:
        ROLE_MODO:        ROLE_USER
        ROLE_ADMIN:       ROLE_MODO
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_MODO, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        mobile:
            pattern:  ^/m
            anonymous: ~
            form_login:
                check_path: /m/login_check
                login_path: /m/login
                default_target_path: /m/admin
            logout:
                path:   /m/logout
                target: /

        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:       true
            anonymous:    true
            switch_user:  true
            remember_me:
                key:      "%secret%"
                lifetime: 31536000
                path:     /
                domain:   ~

    always_authenticate_before_granting: true

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/m/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
MobileController.php

<?php

namespace Acme\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContext;

class MobileController extends Controller
{

    public function loginAction(Request $request)
    {
        /** @var $session \Symfony\Component\HttpFoundation\Session\Session */
        $session = $request->getSession();

        // get the error if any (works with forward and redirect -- see below)
        if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
        } elseif (null !== $session && $session->has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
            $session->remove(SecurityContext::AUTHENTICATION_ERROR);
        } else {
            $error = '';
        }

        if ($error) {
            // TODO: this is a potential security risk (see http://trac.symfony-project.org/ticket/9523)
            $error = $error->getMessage();
        }
        // last username entered by the user
        $lastUsername = (null === $session) ? '' : $session->get(SecurityContext::LAST_USERNAME);

        $csrfToken = $this->container->has('form.csrf_provider')
            ? $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate')
            : null;

        return $this->render('AcmeUserBundle:Mobile:login.html.twig', array(
            'last_username' => $lastUsername,
            'error'         => $error,
            'csrf_token' => $csrfToken,
        ));
    }

尝试这样编写服务声明:

services:
myservice:
    class: My\MyBundle\MyService
    arguments: [ @router ]
    scope: request

我认为您错过了scope属性。

您不必通过“侦听器” 最好的方法是通过安全检查

security.yml:

firewalls:

    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false

    mobile:
        pattern:  ^/m
        anonymous: ~
        form_login:
            check_path: /m/login_check
            login_path: /m/login
            default_target_path: /m/admin
        logout:
            path:   /m/logout
            target: /

    main:
        pattern:  ^
        anonymous: ~
        form_login:
            check_path: /login_check
            login_path: /login
            default_target_path: /admin
        logout:
            path:   /logout
            target: /


access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/m/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
routing.yml:

mobile_login:
    pattern:  /m/login
    defaults: { _controller: AcmeUserBundle:Mobile:login  }

mobile_check_special:
    pattern:  /m/login_check

mobile_logout_special:
    pattern:  /m/logout

尝试以下未经测试的方法:

security.yml:

...

firewalls:
    some_area:
        ...

        form_login:
            failure_handler: custom.security.authentication_failure_handler
            login_path: /login
            check_path: /login_check

        logout:
            path:   /logout
            target: /

...
AuthenticationFailureHandler.php

class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{

    private $router;

    public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null, RouterInterface $router)
    {
        parent::__construct($httpKernel, $httpUtils, $options, $logger);

        $this->router = $router;
    }

    ....

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {

        if(preg_match("/m\/login/", $_SERVER['HTTP_REFERER'])){
            return $this->httpUtils->createRedirectResponse($request, $this->router->generate('mobile_login'));
        }

        return parent::onAuthenticationFailure($request, $exception);
    }
}
服务配置:

....

<service id="custom.security.authentication_failure_handler" class="%custom.security.authentication_failure_handler.class%" public="false">
    <argument type="service" id="kernel" />
    <argument type="service" id="security.http_utils" />
    <argument type="collection" />
    <argument type="service" id="logger"  on-invalid="ignore" />
    <argument type="service" id="router" />
</service>
....
。。。。
....

显示您如何为侦听器定义服务以及您的手机登录路径。@jakon我编辑过。如果您需要更多信息,请告诉我。获取错误:InactiveScopeException:您无法创建非活动范围(“请求”)的服务(“acme.security.authentication\u failure\u event\u listener”)。您是否可以在服务声明末尾添加lazy:true,然后重试!删除作用域和惰性选项并更改您的响应,如下所示:AuthenticationFailureEvent(AuthenticationFailureEvent$event){if(preg_match(“/m\/login/”,$\u SERVER['HTTP\u REFERER']){$url=$this->router->generate('mobile\u login');$response=new RedirectResponse($url);$event->setResponse($response);}看看这篇文章,我想你也必须添加内核控制器功能:同样,我进入m/login,输入错误登录,然后被重定向到/login,并显示错误消息。我完全安全地编辑了我的第一篇文章。ymlCan你能给我看操作代码=>AcmeUserBundle:Mobile:login不好,我是个白痴,忘了更改
....

<service id="custom.security.authentication_failure_handler" class="%custom.security.authentication_failure_handler.class%" public="false">
    <argument type="service" id="kernel" />
    <argument type="service" id="security.http_utils" />
    <argument type="collection" />
    <argument type="service" id="logger"  on-invalid="ignore" />
    <argument type="service" id="router" />
</service>
....