首页 > 解决方案 > Symfony 3 - 手动处理登录过程

问题描述

我尝试使用如下定义的服务手动处理整个登录过程

<?php

namespace StandardBundle\Security;

use \PDO;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class AuthenticateUser
{
    private $sesion;
    private $security;
    private $em;
    private $factory;

    public function __construct(SessionInterface $session, TokenStorageInterface $security, EntityManagerInterface $em, EncoderFactoryInterface $factory)
    {
        $this->session = $session;
        $this->security   = $security;
        $this->em      = $em;
        $this->factory = $factory;
    }

    public function identification($login, $passw)
    {
        if( ('' === $login || null === $login) || ('' === $passw || null === $passw) ) {
            throw new \InvalidArgumentException('Login and password can\'t be empty');
        }

        // getRepo
        $repo = $this->em->getRepository("StandardBundle:User");

        // getUser
        $user = $repo->findOneBy(array('username' => $login));

        // check user exists
        if(!$user){
            return false;
        }

        // get encoder
        $encoder = $this->factory->getEncoder($user);

        // get salt
        $salt = $user->getSalt();

        // Check password is valid
        if(!$encoder->isPasswordValid($user->getPassword(), $passw, $salt)) {
            throw new BadCredentialsException('Bad credentials');
        }

        // generate token
        $token = new UsernamePasswordToken($user, $user->getPassword(), 'main', array('ROLE_VISITEUR'));
        // set token
        $this->security->setToken($token);

        // If the firewall name is not main, then the set value would be instead:
        // $this->get('session')->set('_token_XXXFIREWALLNAMEXXX', serialize($token));
        $this->session->set('_token_main', serialize($token));
        // save
        $this->session->save();
    }
}

这是控制器中的 loginAction

<?php

public function loginAction(Request $request)
  {
    if ($this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
      return $this->redirectToRoute('home');
    }

    if ($request->isMethod('POST')){
        $authenticateUser = $this->get("standard.authenticate_user");
        $authenticateUser->identification('fakeuser','myfakepassw');
    }

    $authenticationUtils = $this->get('security.authentication_utils');

    // get the login error if there is one
    $error = $authenticationUtils->getLastAuthenticationError();

    $lastUsername = $authenticationUtils->getLastUsername();

    $defaultData = array(
      //'action' => $this->generateUrl('login_check')
      'action' => $this->generateUrl('login_' . $request->getLocale())
    );

    $form = $this->createForm(LoginForm::class, array(), $defaultData);
    $form->get('_username')->setData($lastUsername);
    $form->get('_failure_path')->setData($request->getPathInfo());

    $form->handleRequest($request);

    if (!is_null($error)) {
      $form->addError(
        new FormError($error->getMessage())
      );      
    }

    return $this->render('@Standard/login.html.twig', array(
      'form' => $form->createView()
    ));
  }

还有我的 login.twig.html

{{ form_start(form) }}

    {% form_theme form _self %}

    {% block form_errors %}
      {% if errors is defined and errors|length > 0 %}
        <div class="alert alert-danger">
          {% for error in errors %}
            <div>{{ error.message|trans }}</div>
          {% endfor %}
        </div>
      {% endif %}      
    {% endblock %}

    {{ form_errors(form) }}    

    <div class="form-group">
      {# Génération du label. #}
      {{ form_label(form.login, "LibLogin") }}
      {{ form_widget(form.login, {'attr': {'class': 'form-control'}}) }}
    </div>
    <div class="form-group">
      {# Génération du label. #}
      {{ form_label(form.passw, "LibPassw") }}
      {{ form_widget(form.passw, {'attr': {'class': 'form-control'}}) }}      
    </div>
      {{ form_widget(form.submit, {'label':'LibConnexion','attr': {'class': 'btn btn-primary'}}) }}

    {{ form_end(form) }}

它似乎运作良好,但是当提供不正确的信息时,我的服务会抛出一个BadCredentialsExceptionsymfony 无法捕获并且无法返回的

$authenticationUtils = $this->get('security.authentication_utils');

// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();

预期 在此处输入图像描述 得到 在此处输入图像描述

如何告诉 symfony 以错误的形式显示我的异常?

标签: phpsymfony

解决方案


您是否在模板上显示了表单错误? {{ form_errors(form) }}这样...

或者,您可以使用 FormEvents 对表单执行凭据检查,如下所示。然后像这样处理表单,这意味着如果凭据有效,则表单有效(然后登录用户并重定向),否则显示表单错误。


推荐阅读