Symfony 2 FOS 用户捆绑引导模式 AJAX 登录

Posted

技术标签:

【中文标题】Symfony 2 FOS 用户捆绑引导模式 AJAX 登录【英文标题】:Symfony 2 FOS User Bundle Bootstrap modal AJAX Login 【发布时间】:2013-10-27 01:38:31 【问题描述】:

是否有人已经使用 Symfony 2 和 FOS User Bundle 在 Bootstrap 模式中构建了登录表单?

这是我现在拥有的:

src/Webibli/UserBundle/Resources/config/service.yml

authentication_handler:
    class:        Webibli\UserBundle\Handler\AuthenticationHandler
    arguments:    [@router, @security.context, @fos_user.user_manager, @service_container]

app/config/security.yml

form_login:
    provider: fos_userbundle
    success_handler: authentication_handler
    failure_handler: authentication_handler

src/Webibli/UserBundle/Handler/AuthenticationHandler.php

<?php

namespace Webibli\UserBundle\Handler;

use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Exception\AuthenticationException;


class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface


    protected $router;
    protected $security;
    protected $userManager;
    protected $service_container;

    public function __construct(RouterInterface $router, SecurityContext $security, $userManager, $service_container)
    
        $this->router = $router;
        $this->security = $security;
        $this->userManager = $userManager;
        $this->service_container = $service_container;

    
    public function onAuthenticationSuccess(Request $request, TokenInterface $token) 
        if ($request->isXmlHttpRequest()) 
            $result = array('success' => true);
            $response = new Response(json_encode($result));
            $response->headers->set('Content-Type', 'application/json');
            return $response;
        
        else 
            // Create a flash message with the authentication error message
            $request->getSession()->getFlashBag()->set('error', $exception->getMessage());
            $url = $this->router->generate('fos_user_security_login');

            return new RedirectResponse($url);
        

        return new RedirectResponse($this->router->generate('anag_new')); 
     
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) 

        if ($request->isXmlHttpRequest()) 
            $result = array('success' => false, 'message' => $exception->getMessage());
            $response = new Response(json_encode($result));
            $response->headers->set('Content-Type', 'application/json');
            return $response;
        
        return new Response();
    

这是我正在加载到 Bootstrap 模式中的 Twig 视图:

% extends 'UserBundle::layout.html.twig' %
% trans_default_domain 'FOSUserBundle' %
% block user_content %
<script>
    $('#_submit').click(function(e)
        e.preventDefault();
        $.ajax(
            type        : $('form').attr( 'method' ),
            url         : $('form').attr( 'action' ),
            data        : $('form').serialize(),
            success     : function(data, status, object) 
                console.log( status );
                console.log( object.responseText );
            
    );
);
</script>
<div class="modal-dialog">
    <div class="modal-content">
        <form action=" path("fos_user_security_check") " method="post" role="form" data-async data-target="#rating-modal" class="text-left">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h4 class="modal-title"> 'layout.login'|trans </h4>
        </div>
        <div class="modal-body">
            % if error %
                <div> error|trans </div>
            % endif %
            <input type="hidden" name="_csrf_token" value=" csrf_token " />
            <div class="form-group container">
                <label for="email"> 'security.login.username_email'|trans </label>
                <input type="text" class="form-control" id="username" name="_username" value=" last_username " required="required" placeholder="adresse@email.com">
            </div>
            <div class="form-group container">
                <label for="password"> 'security.login.password'|trans </label><br />
                <input type="password" id="password" name="_password" required="required" class="form-control" placeholder="********">
            </div>
            <div class="form-group container">
                <label for="remember_me">
                    <input type="checkbox" id="remember_me" name="_remember_me" value="on" />
                     'security.login.remember_me'|trans 
                </label>
            </div>
        </div>
        <div class="modal-footer">
          <input type="submit" id="_submit" name="_submit" value=" 'security.login.submit'|trans " class="btn btn-primary">
        </div>
    </form>
</div>
</div>
% endblock %

登录表单在没有 AJAX 的情况下工作得非常好。如果出现问题,我只是试图在模式中的表单上出现错误,或者如果登录成功则重定向用户。

谁能解释一下如何做到这一点?

【问题讨论】:

AJAX 什么时候不起作用,你可以尝试实现错误回调,看看你从服务器得到什么响应,如果有的话。 我总是成功,因为请求正在工作,但登录不成功,我不知道如何让 Symfony 返回 JSON 中的错误消息而不是 Flash 消息。目前,AJAX 调用的响应始终是一个完整的 HTML 页面,这很烦人,因为我只想要应该进入模式的内容。 【参考方案1】:

我找到了解决方案。这是我添加到我的 javascript 中的内容,

<script>
    $(document).ready(function()
        $('#_submit').click(function(e)
            e.preventDefault();
            $.ajax(
                type        : $('form').attr( 'method' ),
                url         : ' path("fos_user_security_check") ',
                data        : $('form').serialize(),
                dataType    : "json",
                success     : function(data, status, object) 
                    if(data.error) $('.error').html(data.message);
                ,
                error: function(data, status, object)
                    console.log(data.message);
                
            );
        );
    );
</script>

这是我的处理程序中的onAuthenticationFailure 方法,

public function onAuthenticationFailure(Request $request, AuthenticationException $exception) 
    $result = array(
        'success' => false, 
        'function' => 'onAuthenticationFailure', 
        'error' => true, 
        'message' => $this->translator->trans($exception->getMessage(), array(), 'FOSUserBundle')
    );
    $response = new Response(json_encode($result));
    $response->headers->set('Content-Type', 'application/json');

    return $response;

我认为是我的 Ajax 方法中的 URL 错误。谢谢你的建议。

【讨论】:

【参考方案2】:

我猜你要找的是这个:Symfony2 ajax login。

你的 javascript 看起来会……像这样:

$('#_submit').click(function(e)
        e.preventDefault();
        $.ajax(
            type        : $('form').attr( 'method' ),
            url         : $('form').attr( 'action' ),
            data        : $('form').serialize(),
            success     : function(data, status, object) 
                if (data.sucess == false) 
                    $('.modal-body').prepend('<div />').html(data.message);
                 else 
                    window.location.href = data.targetUrl;
                
            
    );

您还必须修改 onAuthenticationSuccess-Method 的 isXmlHttpRequest-部分:

[...]
if ($request->isXmlHttpRequest()) 
            $targetUrl = $request->getSession()->get('_security.target_path');
            $result = array('success' => true, 'targetUrl' => targetUrl );
            $response = new Response(json_encode($result));
            $response->headers->set('Content-Type', 'application/json');
            return $response;
        
[...]

【讨论】:

似乎是一个好的开始。我试过你的实现,唯一的问题是我总是成功地使用“真”值,从不假...... 很好 :) 你介意将我的答案标记为解决方案吗?

以上是关于Symfony 2 FOS 用户捆绑引导模式 AJAX 登录的主要内容,如果未能解决你的问题,请参考以下文章

Symfony,FOS 用户:使用空输入密码编辑用户

FOS 捆绑包 - 如何选择具有特定角色的用户?

Symfony2 - 安装了 FOS 用户包的自定义身份验证提供程序

FOS 捆绑用户 - 多个角色

Symfony FOS 用户包 - 删除表单和视图中的用户名

使用 FOS 用户 Symfony 4 登录后重定向问题