我正在尝试在监听器中进行重定向,但它不起作用。
我的听众:
<?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'));
}
}
}
我需要这个,因为我有2种登录表单:一种用于PC,一种用于移动。因此,如果用户在登录/传递时出错,我需要显示正确的页面 / login 或 / m / login 。
我的脚本有效。如果我取消注释var_dump('Hello');
,我会看到“你好”。除了重定向之外,所有工作都很好。我不知道为什么。我没有错误,symfony只是不在乎并将我重定向到 / login 。显然它是“正常的”我并不是唯一一个解决这个问题的人,但我找不到解决方案。我刚读到某个地方,我需要一个Dispacher,但我不知道它是如何工作的。
如果你有一个很棒的解决方案。
修改
我的UserBundle / [...] / service.yml
# authentication failure event listener
acme_user.security.authentication_failure_event_listener:
class: Acme\UserBundle\Listener\AuthenticationListener
arguments: [@router]
tags:
- { name: kernel.event_listener, event: security.authentication.failure, method: onAuthenticationFailure }
# authentication success event listener
acme_user.security.interactive_login_listener:
class: Acme\UserBundle\Listener\AuthenticationListener
arguments: [@router]
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onAuthenticationSuccess }
我的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,
));
}
答案 0 :(得分:2)
你不必通过“听众” 最好的方法是通过安全性
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
答案 1 :(得分:1)
尝试这样的事情,未经测试:
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>
....
答案 2 :(得分:0)
尝试编写这样的服务声明:
services:
myservice:
class: My\MyBundle\MyService
arguments: [ @router ]
scope: request
我认为你错过了范围属性。