FOSUserBundle AJAX登录Symfony2(路由)

FOSUserBundle AJAX Login with Symfony2 (routing)

本文关键字:路由 Symfony2 AJAX 登录 FOSUserBundle      更新时间:2024-03-22

我正在尝试使用FOSUserBundle进行AJAX身份验证。

我创建了一个带有AuthenticationHandler class:的Handler目录

<?php
namespace BirdOffice'UserBundle'Handler;
use Symfony'Component'HttpFoundation'Response;
use Symfony'Component'HttpFoundation'RedirectResponse;
use Symfony'Component'Routing'RouterInterface;
use Symfony'Component'HttpFoundation'Session'Session;
use Symfony'Component'Security'Core'Authentication'Token'TokenInterface;
use Symfony'Component'Security'Core'Exception'AuthenticationException;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'Security'Core'SecurityContextInterface;
use Symfony'Component'Security'Http'Authentication'AuthenticationSuccessHandlerInterface;
use Symfony'Component'Security'Http'Authentication'AuthenticationFailureHandlerInterface;
class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
    private $router;
    private $session;
    /**
     * Constructor
     *
     * @param   RouterInterface $router
     * @param   Session $session
     */
    public function __construct( RouterInterface $router, Session $session )
    {
        $this->router  = $router;
        $this->session = $session;
    }
    /**
     * onAuthenticationSuccess
     *
     * @param   Request $request
     * @param   TokenInterface $token
     * @return  Response
     */
    public function onAuthenticationSuccess( Request $request, TokenInterface $token )
    {
        // if AJAX login
        if ( $request->isXmlHttpRequest() ) {
            $array = array( 'success' => true ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
            return $response;
            // if form login
        } else {
            if ( $this->session->get('_security.main.target_path' ) ) {
                $url = $this->session->get( '_security.main.target_path' );
            } else {
                $url = $this->router->generate( 'home_page' );
            } // end if
            return new RedirectResponse( $url );
        }
    }
    /**
     * onAuthenticationFailure
     *
     * @param   Request $request
     * @param   AuthenticationException $exception
     * @return  Response
     */
    public function onAuthenticationFailure( Request $request, AuthenticationException $exception )
    {
        // if AJAX login
        if ( $request->isXmlHttpRequest() ) {
            $array = array( 'success' => false, 'message' => $exception->getMessage() ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
            return $response;
            // if form login
        } else {
            // set authentication exception to session
            $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);
            return new RedirectResponse( $this->router->generate( 'login_route' ) );
        }
    }
}

我创建了一个login Javascript function:

function login() {
    $.ajax({
        type: "POST",
        url: Routing.generate('check_login_ajax'),
        dataType: 'json',
        data: {
            _username: $('#username').val(),
            _password: $('#password').val(),
            _remember_me: false,
            _csrf_token: $('#_csrf_token').val()
        }
    }).done(function(data) {
        console.log(data);
    }).fail(function(data) {
        console.log(data);
    });
}

在我的routingAjax.yml中,我添加了以下行来覆盖FOSUserBundle security route:

check_login_ajax:
    pattern:  /check_login_ajax
    defaults: { _controller: FOSUserBundle:Security:check }
    requirements:
        _method:  POST
    options:
        expose: true

在我的全局security.yml文件中,我添加了check_pathsuccess_handlerfailure_handler部分:

firewalls:
        main:
            pattern: ^/
            form_login:
                login_path: fos_user_registration_register
                check_path:      check_login_ajax
                success_handler: user.security.authentication_handler
                failure_handler: user.security.authentication_handler
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:
                  path:   fos_user_security_logout
                  target: /
            anonymous:    true

我的第一个问题是:AJAX返回这样的消息:"无效的CSRF令牌。"。这是我的PHP代码:

<?php
  $csrfProvider = $this->container->get('form.csrf_provider');
  $csrfToken = $csrfProvider->generateCsrfToken('popUpUser');
?>

第二个问题:我的登录页面(不是AJAX页面)不再工作,因为FOSUserBundle登录的原始路径已被覆盖。

PS:我昨天发布了一条消息:FOSUserBundle(登录/注册)+AJAX+Symfony2,但我对我的问题解释得很糟糕。提前道歉。

第一个问题:您正在发送无效的CSRF令牌。在Symfony 2.3中,您可以在模板的inputvalue中使用{{ csrf_token('authenticate') }}生成它。

第二个问题:不要覆盖路由,只需使用原始路由:fos_user_security_check

一般来说:如果你使用AuthenticationSuccessHandler扩展Symfony'Component'Security'Http'Authentication'DefaultAuthenticationSuccessHandler,你的方法可能看起来像这样:

public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
    if ($request->isXmlHttpRequest()) {
        return new JsonResponse(array('success' => true));
    }
    return parent::onAuthenticationSuccess($request, $token);
}

对扩展Symfony'Component'Security'Http'Authentication'DefaultAuthenticationFailureHandlerAuthenticationFailureHandler执行类似操作。