Symfony 的 Guard start() 函数不起作用

Symfony's Guard start() function not working

我是 Symfony 的新手,正在学习如何使用 Guard 对用户进行身份验证。目前使用 Symfony 2.8.4.

你可以在下面查看我的所有代码,它们大部分来自我在网上找到的各种教程。

FormLoginAuthenticator class 中的 start() 函数似乎没有正确检测凭据是否已发送。如果我访问 /login、/homepage、/login_check 等任何页面。我会在所有这些页面上得到相同的 return:

{"message":"Username could not be found."}

这是我的 FormLoginAuthenticator.php:

namespace AppBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Doctrine\ORM\EntityManager;

class FormLoginAuthenticator extends AbstractGuardAuthenticator
{
    private $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    /*
     * This method will get called on every request that requires an authentication.
     * Its job is to read the authentication information contained in the request, and return it.
     */
    public function getCredentials(Request $request)
    {
        return array(
            'username' => $request->request->get('_username'),
            'password' => $request->request->get('_password'),
        );
    }

    /*
     * After getting the credentials, try to get the User associated with those credentials.
     * The value of the credentials is passed to getUser() as the $credentials argument.
     * The job of this method is to return an object implementing UserInterface.
     * If it does, the next step of the authentication will be called: checkCredentials().
     * Else, the authentication will fail and the method onAuthenticationFailure() will get called.
     */
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        return $userProvider->loadUserByUsername($credentials['username']);
    }

    /*
     * The job of this method is to check if the credentials of the previously returned User are correct.
     * If it returns true, the user will be authenticated, and the method onAuthenticationSuccess() will be called.
     * If does not, the authentication fails and the method onAuthenticationFailure() is called.
     */
    public function checkCredentials($credentials, UserInterface $user)
    {
        $plainPassword = $credentials['password'];
        $encoder = $this->container->get('security.password_encoder');
        if (!$encoder->isPasswordValid($user, $plainPassword)) {
            throw new BadCredentialsException();
        }
    }

    /*
     * This method is called when the user is successfully authenticated.
     * It can return null, in which case the request continues to process as expected,
     * or return a Response object, in which case this Response will be transferred to the user.
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        $url = $this->router->generate('homepage');

        return new RedirectResponse($url);
    }

    /*
     * This method is called when the authentication fails.
     * Its job is to return a Response object that will be sent to the client.
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $data = array(
            'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
        );

        return new JsonResponse($data, 403);
    }

    /*
     * This gets called when the user tries to access a resource that requires authentication,
     * but no authentication information was found in the request.
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $url = $this->router->generate('security_login');
        return new RedirectResponse($url);
    }

    protected function getLoginUrl()
    {
        return $this->container->get('router')
            ->generate('security_login');
    }

    protected function getDefaultSuccessRedirectUrl()
    {
        return $this->container->get('router')
            ->generate('homepage');
    }

    public function supportsRememberMe()
    {
        return false;
    }
}

这是我的 SecurityController.php:

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class SecurityController extends Controller
{
    /**
     * @Route("/login", name="security_login")
     */
    public function loginAction()
    {
        $helper = $this->get('security.authentication_utils');
        return $this->render('security/login.html.twig', array(
            'error' => $helper->getLastAuthenticationError(),
        ));
    }

    /**
     * @Route("/login_check", name="security_login_check")
     */
    public function loginCheckAction()
    {
        // will never be executed
    }
}

security.yml 文件:

security:
    providers:
        your_db_provider:
            entity:
                class: AppBundle:User

    encoders:
        AppBundle\Entity\User: bcrypt

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: ~
            logout: ~

            guard:
                authenticators:
                    - app.form_login_authenticator

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/, roles: ROLE_ADMIN }

最后 services.yml 文件:

parameters:

services:
    app.form_login_authenticator:
        class: AppBundle\Security\FormLoginAuthenticator
        arguments: ['@doctrine.orm.entity_manager']

将此添加到 getCredentials() 可以解决这个特定问题,但还有更多问题需要解决:

if ($request->getPathInfo() != '/login_check') {
    return;
}