【问题标题】:[Symfony][FOSUserBundle] Authentification from bootstrap modal / Lost Session[Symfony][FOSUserBundle] 来自引导模式/丢失会话的身份验证
【发布时间】:2023-03-29 13:41:01
【问题描述】:

我遇到了一个让我抓狂的 FOSUserBundle 错误:

我使用引导模式进行身份验证,如下所示:

<div class="modal fade" id="modalLogin" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-body"></div>
        </div>
    </div>
</div>

我使用链接到 FOS 登录 URL (fos_user_security_login) 的 Ajax 请求加载模态体:

$(".connectModal").bind("click", function() {
$.ajax({
    url: $('#path_login').val(),
    success: function (data) {
        $('#modalLogin .modal-body').html(data);
        $('#modalLogin').modal()
    }
});

});

然后,在我的模式中,我使用 Ajax 来检查身份验证。所以我使用:

$('#form_login').submit( function(e) {
      e.preventDefault();
      e.stopImmediatePropagation();
      $.ajax({
          url: {{ path("fos_user_security_check") }},
          type: "post",
          data: {_csrf_token: $('#csrf_token').val(), _username: $('#username').val(), _password: $('#password').val(), _remember_me: 'on'},
          dataType: 'json',
          complete: function (data, statut) {
              if (statut == 'success') {
                  $('#modalLogin').modal('hide');
              }
          },
          error : function(resultat, statut, error){
              $('#error_message').text(JSON.parse(resultat.responseText).message);
              $('#error_block').show();
          }
      });
  });

一切都很好!如果身份验证失败,我会收到错误并显示它。如果身份验证正常,我会在 Symfony 会话中获取用户(我可以在 Symfony 的调试控制台中检查它)。

但是一旦我关闭我的模式,经过身份验证的用户就不会在网站的会话中传播(是否有不同的用户?!?)。我保持匿名状态... :( 而且我真的不想再去哪里调查了……这是 Symfony 的问题吗? FOSUserBundle? jQuery?

最后,这是我的安全防火墙:

profil:
        pattern: ^/account/
        security: true
        provider: fos_userbundle
        context: _security_login
        form_login:
            login_path: fos_user_security_login
            check_path: fos_user_security_check
            csrf_token_generator: security.csrf.token_manager
            success_handler: juser.success_handler
            failure_handler: juser.failure_handler
            default_target_path: /account
        logout:
            path: fos_user_security_logout
            target: /
        remember_me:
            key: "%secret%"
            lifetime: 86400

我的成功处理程序:

    <?php

namespace JUserBundle\Handler;


use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Response;

class AuthenticationSuccessHandler extends DefaultAuthenticationSuccessHandler
{
    /**
     * Router
     * @var \Symfony\Component\Routing\RouterInterface
     */
    private $router;

    /**
     * Translator
     * @var \Symfony\Component\Translation\TranslatorInterface
     */
    private $translator;

    /**
     * AuthenticationSuccessHandler constructor.
     * @param HttpUtils $httputils
     * @param RouterInterface $router
     * @param TranslatorInterface $translator
     */
    public function __construct(HttpUtils $httputils, RouterInterface $router, TranslatorInterface $translator)
    {
        parent::__construct($httputils);

        $this->router = $router;
        $this->translator = $translator;
    }

    /**
     * Callback sur l'authentification réussie
     * @param Request $request
     * @param TokenInterface $token
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token) {
        if($request->isXmlHttpRequest()){
            $data = array(
                'success'=> 1,
                'url' => $this->router->generate('fos_user_profile_show')
            );

            return new JsonResponse($data);
        }else{
            return parent::onAuthenticationSuccess($request, $token);
        }
    }

    /**
     * Définit le traducteur
     * @param \Symfony\Component\Translation\TranslatorInterface $translator
     */
    function setTranslator(TranslatorInterface $translator) {
        $this->translator = $translator;
    }
}

我的失败处理程序:

    <?php

namespace JUserBundle\Handler;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\RouterInterface;

class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
    /**
     * Router
     * @var \Symfony\Component\Routing\RouterInterface
     */
    private $router;

    /**
     * Translator
     * @var \Symfony\Component\Translation\TranslatorInterface
     */
    private $translator;

    /**
     * AuthenticationFailureHandler constructor.
     * @param HttpKernelInterface $httpKernel
     * @param HttpUtils $httputils
     * @param RouterInterface $router
     * @param TranslatorInterface $translator
     */
    public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httputils, RouterInterface $router, TranslatorInterface $translator)
    {
        parent::__construct($httpKernel, $httputils);

        $this->router = $router;
        $this->translator = $translator;
    }

    /**
     * Callback sur l'authentification échouée
     * @param Request $request
     * @param AuthenticationException $exception
     * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
        if($request->isXmlHttpRequest()){
            $message = $exception->getMessageKey();
            $messageTrans = $this->translator->trans($message,array(),'FOSUserBundle');
            if($messageTrans === $message){
                $messageTrans = $this->translator->trans($message,array(),'security');
            }
            $data = array(
                'message' => $messageTrans,
            );

            return new JsonResponse($data,401);
        }else{
            return parent::onAuthenticationFailure($request, $exception);
        }
    }

    /**
     * Définit le traducteur
     * @param \Symfony\Component\Translation\TranslatorInterface $translator
     */
    function setTranslator(TranslatorInterface $translator) {
        $this->translator = $translator;
    }
}

非常感谢您的支持!

【问题讨论】:

  • 嘿 Jérémie,我认为您应该检查 symfony 响应您的请求发送的会话 cookie 是否设置正确。 (从你所描述的 - 听起来好像没有)上次我遇到类似的问题是因为跨域请求,所以你应该确保cookie域和你使用的域匹配
  • 感谢您的回复。我检查了返回的 cookie,它似乎很好(如果我与其他应用程序进行比较)。这是:REMEMBERME=SlVzZXJCdW5kbGVcRW50aXR5XFVzZXI6YW1SaGNtRjFiSFE9OjE1MTcyMTUxMDU6MWQ5YTBkNTIyZGQ1YTllNzdiNjcwZjMwMjk3NjUxN2E5YzU0YTVkYTIwMGMwMjEzZDllN expires=星期一,2018 年 1 月 29 日 08:38:25 GMT;路径=/; httponly

标签: php jquery ajax twitter-bootstrap symfony


【解决方案1】:

对于遇到同样问题的人,我终于找到了问题的答案。 我已在所有 FOSUserBundle 路由前加上 /account。

结果是生成的cookie与我尝试登录的域不对应,即cookie是为mydomain/account而不是mydomain生成的...

所以我删除了路由前缀并修改了我的防火墙。

【讨论】:

    猜你喜欢
    • 2014-04-08
    • 2017-01-24
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 2014-09-22
    • 2018-05-10
    相关资源
    最近更新 更多