Symfony 2.3登录表单是';t身份验证


Symfony 2.3 login form isn't authenticating

我正试图用Symfony2.3实现一个相当基本的登录表单,但我遇到了一个错误,有时在提供正确的凭据后重定向到期望的页面,但有时没有(相反,我只是重定向回登录页面)。这是我的security.yml文件:

security:
    encoders:
        Symfony'Component'Security'Core'User'User: plaintext
        Acme'MyBundle'Entity'User: sha512
    providers:
        main:
            id: acme.user.provider
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login_firewall:
            pattern: ^/login$
            security: false
        secured_area:
            pattern: ^/
            form_login: ~
            logout:
                path:   /logout
                target: /
    access_control:
        - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
        - { path: ^/, roles: ROLE_USER, requires_channel: https }

这是我的SecurityController:

<?php
namespace Acme'MyBundle'Controller;
use Sensio'Bundle'FrameworkExtraBundle'Configuration'Route;
use Sensio'Bundle'FrameworkExtraBundle'Configuration'Template;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'Security'Core'SecurityContextInterface;
/**
 * Class SecurityController
 * @package Acme'MyBundle'Controller
 *
 * @Route("/")
 */
class SecurityController extends Controller
{
    /**
     * @param Request $request
     * @return 'Symfony'Component'HttpFoundation'Response
     *
     * @Route("/login", requirements={"_scheme" = "https"}, path="login")
     */
    public function LoginAction(Request $request)
    {
        $session = $request->getSession();
        // get the login error if there is one
        if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
            $error = $request->attributes->get(
                SecurityContextInterface::AUTHENTICATION_ERROR
            );
        } elseif (null !== $session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
            $error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR);
            $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
        } else {
            $error = '';
        }
        // last username entered by the user
        $lastUsername = (null === $session) ? '' : $session->get(SecurityContextInterface::LAST_USERNAME);
        return $this->render(
            'AcmeMyBundle:Security:login.html.twig',
            array(
                // last username entered by the user
                'last_username' => $lastUsername,
                'error'         => $error,
            )
        );
    }
    /**
     * @Route("/login_check", requirements={"_scheme" = "https"}, path="login_check")
     */
    public function LoginCheckAction()
    {
    }
    /**
     * @Route("/logout", requirements={"_scheme" = "https"}, path="logout")
     */
    public function LogoutAction()
    {
    }
}

这是我的捆绑包的routing.yml文件:

_security:
    resource: "@AcmeMyBundle/Controller/SecurityController.php"
    type: annotation

当我提供正确的凭据时,大约20%的时间我会正确登录/重定向到给定的URL。其他80%的时间我只是被重定向回表单登录页面,没有错误消息。当我尝试使用不正确的凭据登录时,我也没有看到任何错误消息。

更新:问题似乎是Symfony在我的数据库中为每个请求创建了多个会话。我正在使用pdo处理程序。

去掉你的login_firewall,这是不需要的,因为你有一个允许匿名访问登录页面的access_control规则。防火墙越少越好。

我怀疑,当你无法登录时,你是在直接访问你的登录页面(/login),因此,试图在你的"login_firewall"下登录,这是无用的,因为这只对/login页面有好处。在login_firewall下登录后,您将被重定向到/,但您没有在"secured_area"防火墙(保护/)下进行身份验证,因此它要求您再次登录,但这次是在正确的防火墙下。我想这一次你可以登录了。

这可能是问题所在,但无论如何,请删除您的login_firewall

事实证明,问题实际上与我存储会话的Session实体/表有关。我使用PDOSessionHandler将会话存储在数据库中,并且在我的ORM Session实体中有以下$id

<?php
namespace Acme'MyBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
/**
 * Session
 *
 * @ORM'Table()
 * @ORM'Entity
 */
class Session
{
    /**
     * @var integer
     *
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;

$id不应该是integer类型,而应该是(显然是(-_-)字符串类型。将属性更改为:之后

/**
 * @var integer
 *
 * @ORM'Column(type="string", length=255)
 * @ORM'Id
 */
private $id;

并且运行php app/console doctrine:schema:update --force,一切似乎都正常工作。