身份验证在Symfony2中无提示失败

时间:2011-09-22 14:49:45

标签: authentication symfony

我无法让身份验证工作,但它似乎只在非常特殊的情况下发生。身份验证是通过第三方API完成的,所以我编写了自己的用户提供程序类,在该类中是一些同步API和Symfony之间数据的代码,作为同步过程的一部分,它决定了用户应该拥有哪些角色。 执行此操作后,它通过ManyToMany关系设置角色和用户之间的关系。

我的User对象中的getRoles()方法从数据库中获取角色对象并将其转换为字符串数组,角色名称来自我的数据库,并且都以ROLE _开头。

如果我使用一个没有额外角色的帐户登录,它可以正常工作,但是如果我登录到应该有角色的帐户,我只会被发送回登录屏幕而没有错误消息。

我检查了日志并看到了这些条目:

security.INFO: User "test105@example.com" has been authenticated successfully [] []
event.DEBUG: Notified event "security.interactive_login" to listener "Pogo\MyBundle\Listener\LoginListener::onSecurityInteractivelogin". [] []
event.DEBUG: Listener "Symfony\Component\Security\Http\Firewall::onKernelRequest" stopped propagation of the event "kernel.request". [] []
event.DEBUG: Listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener" was not called for event "kernel.request". [] []
event.DEBUG: Listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener" was not called for event "kernel.request". [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\Security\Http\Firewall\ContextListener::onKernelResponse". [] []
security.DEBUG: Write SecurityContext in the session [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ResponseListener::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\SecurityBundle\EventListener\ResponseListener::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bridge\Monolog\Handler\FirePHPHandler::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.response" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener::onKernelResponse". [] []
event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onEarlyKernelRequest". [] []
event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
security.INFO: Populated SecurityContext with an anonymous Token [] []
event.DEBUG: Notified event "kernel.exception" to listener "Symfony\Component\Security\Http\Firewall\ExceptionListener::onKernelException". [] []
security.DEBUG: Access denied (user is not fully authenticated); redirecting to authentication entry point [] []
security.DEBUG: Calling Authentication entry point [] []

我不明白它是如何在顶部进行身份验证的,然后一旦它检查防火墙就会发现自己有一个匿名令牌,这就是为什么它可能会把我送回登录界面。

我的防火墙/ access_control设置是:

firewalls:
    public:
        pattern: /.*
        anonymous: true
        tessitura_login:
            login_path: /account/login
            check_path: /secure/login_check
        logout:
            path: /secure/logout
            target: /
access_control:
    - { path: ^/secure/.*, role: ROLE_USER }
    - { path: ^/admin.*, role: ROLE_ADMIN }
    - { path: ^/account/login/?, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: /.*, role: IS_AUTHENTICATED_ANONYMOUSLY }

对此的任何帮助都会受到高度赞赏,我现在花了几个小时就完成了这件事。我完全被难过了。

6 个答案:

答案 0 :(得分:2)

在使用电话号码作为用户名并且未在refreshUser()方法中指定用户名属性时出现此无提示失败问题,该方法应为:

public function refreshUser(UserInterface $customer)
{
    $class = get_class($customer);

    if( !$this->supportsClass($class) ) {
        throw new UnsupportedUserException("Instances of \"{$class}\" are not supported");
    }

    return $this->loadUserByUsername($customer->getPhoneNumber()); // <-- This is it!
}

我认为我不是唯一一个错过它的人,可能有所帮助。

答案 1 :(得分:1)

破坏的会话存储对我造成了这种情况。我正在使用PdoSessionHandler并且令人失望地没有给出明确的错误或日志消息。

答案 2 :(得分:0)

我也经历过同样的经历。当我的用户登录时,我会通过以下几个语句检查他的角色:

if(true === $this->get('security.context')->isGranted('ROLE_MANAGER')){
   //return redirect
}
if(true === $this->get('security.context')->isGranted('ROLE_USER')){
   //return redirect
}
//throw error

有些用户不时会收到错误。我想这是因为同样的原因。用户以某种方式进行了身份验证但尚未获得其角色。

我无法重现自己的问题。我刚收到用户的错误报告。

答案 3 :(得分:0)

我也经历过同样的经历。对我而言,这是因为/ tmp分区已满,因此会话可以存储在服务器端,并且可以重定向到nex

答案 4 :(得分:0)

登录我的系统时遇到同样的问题,其中会话被配置为存储在memcache中但memcached未运行。如上所述,遗憾的是它没有给出更好的错误信息。

希望能帮助别人节省一些时间; - )

答案 5 :(得分:0)

我在用户登录时遇到了同样的问题我使用了sonata管理包,我也在使用PdoSessionHandler的数据库会话

session.handler.pdo:
    class:     Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
    arguments: ["@pdo", %pdo.db_options%]

第一个问题,当我创建一个具有大量角色/权限的组时,数据在字段中被截断,因此我使用longtext更改了我的角色字段并更改了ROW_FORMAT=COMPRESSED

ALTER TABLE  `fos_group` CHANGE `roles` `roles` LONGTEXT NOT NULL COMMENT '(DC2Type:array)'; 
ALTER TABLE `fos_group`
    ENGINE=INNODB
    ROW_FORMAT=COMPRESSED 
    KEY_BLOCK_SIZE=8;

它完成工作并将所有角色/权限保存到字段中作为完整的序列化字符串。但是用户无法登录而没有错误消息然后我查看了由app/logs dir中的symfony生成的日志

  

用户已成功通过身份验证

然后重定向到仪表板,但从仪表板重定向生成的日志

  

访问被拒绝(用户未完全通过身份验证)

原因是会话数据在会话表中被截断,所以我也改变了我的会话表,这就完成了工作

ALTER TABLE `session` CHANGE `session_value` `session_value` LONGTEXT NOT NULL; 
ALTER TABLE `session`
    ENGINE=INNODB
    ROW_FORMAT=COMPRESSED 
    KEY_BLOCK_SIZE=8;

我还更新了my.ini文件,并将文件格式更改为Barracuda,默认文件格式为antelop

[mysqld]
innodb_file_per_table
innodb_file_format = Barracuda