Symfony2 FOSUserBundle - 针对“用户活动”进行验证国旗登录 [英] Symfony2 FOSUserBundle – Validate against "user active" flag on login

查看:177
本文介绍了Symfony2 FOSUserBundle - 针对“用户活动”进行验证国旗登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用户标记为'active',如果设置为0或null,我将不允许登录。



我尝试了几种方法如果我做注销路由的Flash消息不保留,所以用户看不到任何东西。




$ b $我看着在登录表单上添加一个验证,以便如果标志没有设置为true,但是在该文件夹(vendor / Bundles / FOS / UserBundle / Form / Type)中,它会抛出一个正常的表单错误为登录表单找不到任何东西,只有注册和这样的,所以我不知道在哪里把它或从哪里继承,以覆盖。



我也试过建议在这里手动注销,但是这就给我留下了一个白屏死亡...

任何建议如何轻易实现这一点?

* ** * ** * ** ** UPDATE ** * ** * * ***



我是alize我可能想要去添加一个验证器在登录表单上。我现在已经把它编码到用户发送到的第一个路由的控制器中,但是如果用户在登录之前键入一个路由,那么这将不会提供很高的安全性,因为在成功的登录尝试之后,我的默认着陆页登录将不会是用户被采取的路线,但他将登陆在他选择的路线上...



*** ** * * >所以服务配置文件有这个...

$ $ p $ < service id =security.user_checkerclass =%security .user_checker.class%public =false/>

这个参数是在这里定义的...

 < parameter key =security.user_checker.class> Symfony \ Component \Security\Core\User\UserChecker< / parameter> 

所以为了修改登录逻辑我需要覆盖

  Symfony \ Component \Security\Core\User\UserChecker 



现在我已经通过在symfony app / config中自己的parameters.ini中覆盖了上面的参数来完成这项工作。



<$ p $ b

$ b $

  //测试companylock ... 
if(!$ user-> getCompany() - > getActive()){
throw new LockedException('该用户的公司被锁定。

$ / code $


这是整个文件:

 <?php 

/ *
*这个文件是Symfony包的一部分。
*
*(c)Fabien Potencier< fabien@symfony.com>
*
*有关完整的版权和许可证信息,请查看随源代码分发的许可
*文件。
* /

//由Mattias覆盖

命名空间BizTV\UserBundle\Controller;
//命名空间Symfony \ Component \Security\Core\User;

使用Symfony \ Component \Security\Core\Exception\CredentialsExpiredException;
使用Symfony \ Component \Security\Core\Exception\LockedException;
使用Symfony \ Component \Security\Core\Exception\DisabledException;
使用Symfony \ Component \Security\Core\Exception\AccountExpiredException;

使用Symfony \ Component \Security\Core\User\UserInterface;
使用Symfony \ Component \Security\Core\User\UserChecker作为OriginalUserChecker;

/ **
UserChecker检查用户帐户标志。
*
* @author Fabien Potencier< fabien@symfony.com>
* /
class UserChecker extends OriginalUserChecker
{
/ **
* {@inheritdoc}
* /
public function checkPreAuth(UserInterface $ user $> getCompany() - > getActive()){$ b $
{b
$ b //测试companylock ...
b抛出新的LockedException('该用户的公司被锁定。',$ user);
}

if(!$ user instanceof AdvancedUserInterface){
return;

$ b $ if(!$ user-> isCredentialsNonExpired()){
throw new CredentialsExpiredException('User credentials has expired。',$ user);




/ **
* {@inheritdoc}
* /
公共功能checkPostAuth(UserInterface $ user)
{

//测试companylock ...
if(!$ user-> getCompany() - > getActive()){
抛出新的LockedException('该用户的公司被锁定。',$ user);
}

if(!$ user instanceof AdvancedUserInterface){
return;



$ b if(!$ user-> isAccountNonLocked()){
throw new LockedException('User account is locked。', $用户);

$ b $ if(!$ user-> isEnabled()){
throw new DisabledException('User account is disabled。',$ user);

$ b $ if(!$ user-> isAccountNonExpired()){
throw new AccountExpiredException('User account has expired。',$ user);


$ b code $
$ b

* 更新nb 3 * ** * ****
现在我只剩下使它实际上检查标准的用户锁,令人惊讶的是,它不是开箱即用。 (感谢nifr让我这么远!)

我的用户实体像这样开始,像Nifr说的,我需要实现AdvancedUserInterface,但这可能不是这样做的方式,因为它仍然不检查这个锁...但它也抛出我没有错误信息要么(如果我改变它们,把实施AdvancedUserInterface,然后扩展baseUser它会引发错误,所以...) / p>

 <?php 
// src / BizTV / UserBundle / Entity / User.php

命名空间BizTV\UserBundle\\Entity;

使用BizTV\UserBundle\Validator\Constraints作为BizTVAssert;
使用Symfony \ Component \Security\Core\User\AdvancedUserInterface;

使用FOS \ UserBundle \Entity\User作为BaseUser;
使用Doctrine \ORM\Mapping作为ORM;

使用BizTV \BackendBundle\Entity\company作为公司;
$ b / **
* @ ORM\Entity
* @ ORM\Table(name =fos_user)
* /
class User扩展BaseUser实现AdvancedUserInterface
{

不知道这是怎么做的,基本的用户,并尝试和实现AdvancedUserInterface,完成上述我仍然不能使用它应该添加的功能(但它也抛出我没有任何错误信息),但如果我切换EXTENDS和IMPLEMENTS这样的地方(第18行)...

 类用户实现AdvancedUserInterface extends BaseUser 

...我得到这个错误:

 解析错误:语法错误,意想不到的T_EXTENDS,预计在第18行的/var/www/cloudsign/src/BizTV/UserBundle/Entity/User.php中有{{'


解决方案

FOSUserBundle / Symfony已经集成了某种主动标志。



FOS \用户捆绑\模型\用户已经提供了属性锁定和启用,基本上是为了这个目的。这两个属性之间的区别如下(引用@ stof的评论 here < a>)
$ b


从安全组件的角度来看,没有真正的
差异:两者都被禁止登录。不同的是一个
的语义之一:被禁用的用户一般是需要
激活账户的用户(例如,当你激活需要
确认FOSUserBundle中的电子邮件时,用户被禁用创建
并在确认时启用)。另一方面,锁定用户通常是网站管理员为禁止用户所做的动作。
在数据库中使用相同的字段是没有意义的,因为
允许被禁止的用户通过简单地通过
确认过程再次访问。


锁定/禁用用户的检查由 UserChecker (symfony提供这一个作为@ security.user_checker)在FOSUserBundle的 AuthenticationListener 它实现 Symfony \ Component \Security\Core\User\UserCheckerInterface

<现在为了将不活动的用户重定向到不同的路线,您应该:


  1. 在扩展的AuthenticationListener的try / catch块中捕获 Symfony \ Component \ Security \Core\Exception\DisabledException

  2. 如果捕获的异常类型为InactiveUserException

,则将用户重定向到某个路由(可选)将重定向移动到新创建的EventListener / -Subscriber将在扩展的AuthenticationListener中分派。通过这种方式,您可以稍后创建其他监听器,例如用于日志记录,只需将它们订阅到非活动用户登录尝试事件即可。


I have a flag on my users for 'active' and if set to zero or null, I will not allow login.

I have tried a couple of approaches and come up short.

If I do the logout route the flash message is not preserved, so the user sees nothing.

I looked into adding a validation on the login form so that it would throw a normal form error if the flag was not set to true, but in that folder (vendor/Bundles/FOS/UserBundle/Form/Type) I find nothing for login form, only registration and such, so I wouldn't know where to put it or where to inherit from in order to override.

I also tried as suggested here to manually log out, but that left me with a white screen of death...

Any suggestions how to easily accomplish this?

************** UPDATE ************

I realized that I probably want to go about it adding a validator on the login form. I currently have it coded into the controller of the first route a user gets sent to, but that won't provide much security if a user types a route before logging in, because on a successful login attempt, my default "landing page" after login will not be the route that the user is taken to, but he will be landing on the route of his choice...

***UPDATE AGAIN ****

So the service config file has this...

    <service id="security.user_checker" class="%security.user_checker.class%" public="false" />

And that parameter is defined here...

    <parameter key="security.user_checker.class">Symfony\Component\Security\Core\User\UserChecker</parameter>

So in order to modify the login logics I need to override

Symfony\Component\Security\Core\User\UserChecker

Now I have done that by overriding that parameter above in my own parameters.ini in the symfony app/config like this

security.user_checker.class  = BizTV\UserBundle\Controller\UserChecker

.. and added this check to my userChecker overrider...

    //Test for companylock...
    if ( !$user->getCompany()->getActive() ) {
        throw new LockedException('The company of this user is locked.', $user);
    }

Here's the entire file:

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

//Override by Mattias

namespace BizTV\UserBundle\Controller;
//namespace Symfony\Component\Security\Core\User;

use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
use Symfony\Component\Security\Core\Exception\LockedException;
use Symfony\Component\Security\Core\Exception\DisabledException;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserChecker as OriginalUserChecker;

/**
 * UserChecker checks the user account flags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UserChecker extends OriginalUserChecker
{
    /**
     * {@inheritdoc}
     */
    public function checkPreAuth(UserInterface $user)
    {

    //Test for companylock...
    if ( !$user->getCompany()->getActive() ) {
        throw new LockedException('The company of this user is locked.', $user);
    }

        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isCredentialsNonExpired()) {
            throw new CredentialsExpiredException('User credentials have expired.', $user);
        }


    }

    /**
     * {@inheritdoc}
     */
    public function checkPostAuth(UserInterface $user)
    {

    //Test for companylock...
    if ( !$user->getCompany()->getActive() ) {
        throw new LockedException('The company of this user is locked.', $user);
    }  

        if (!$user instanceof AdvancedUserInterface) {
            return;
        }



        if (!$user->isAccountNonLocked()) {
            throw new LockedException('User account is locked.', $user);
        }

        if (!$user->isEnabled()) {
            throw new DisabledException('User account is disabled.', $user);
        }

        if (!$user->isAccountNonExpired()) {
            throw new AccountExpiredException('User account has expired.', $user);
        }
    }
}

* Update nb 3 ******** Now I only have left to make it actually check for the standard user lock which surprisingly it doesn't do out of the box. (Thanks nifr for getting me this far!)

My user entity starts off like this, and like Nifr said, I need to implement the AdvancedUserInterface, but this is probably not the way to do it since it still doesn't check for this lock... but it throws me no error message either (if I change them up and put implememts AdvancedUserInterface and then EXTENDs baseUser it throws an error so...)

<?php
// src/BizTV/UserBundle/Entity/User.php

namespace BizTV\UserBundle\Entity;

use BizTV\UserBundle\Validator\Constraints as BizTVAssert;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;

use BizTV\BackendBundle\Entity\company as company;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser implements AdvancedUserInterface
{

Not sure if that's how you do it when you both extend base user and try and implement AdvancedUserInterface, when done as above I still can't use the features it's supposed to add (but it throws me no error message either), but If I switch places of the EXTENDS and IMPLEMENTS like this (line 18)...

class User implements AdvancedUserInterface extends BaseUser 

...I get this error:

Parse error: syntax error, unexpected T_EXTENDS, expecting '{' in /var/www/cloudsign/src/BizTV/UserBundle/Entity/User.php on line 18

解决方案

FOSUserBundle / Symfony already has some kind of "active" flag integrated.

FOS\UserBundle\Model\User already provides the properties "locked" and "enabled" which are intended basically for this purpose. The difference between those two properties is the following ( quoting @stof's comment here)

From the Security component point of view, there is no real difference: both are forbidden to log in. The difference is a semantic one: disabled users are generally users that need to activate their account (for instance, when you activate the need to confirm the email in FOSUserBundle, the user is disabled on creation and enabled on confirmation). On the other hand, locking a user is generally an action done by the admin of the site to ban a user. Using the same field in the database does not make sense as it would allow banned user to have access again by simply going through the confirmation process.

The check for locked/disabled users is being performed by a UserChecker ( symfony provides this one as @security.user_checker ) in FOSUserBundle's AuthenticationListener which implements Symfony\Component\Security\Core\User\UserCheckerInterface.

Now in order to redirect inactive user's to a different route you would:

  1. Catch the Symfony\Component\Security\Core\Exception\DisabledException in the try/catch block in an extended AuthenticationListener
  2. Redirect the user to a certain route if the caught exception is of type InactiveUserException

Optionally move the redirect to a newly created EventListener/-Subscriber which is being dispatched in the extended AuthenticationListener. This way you could later create additional Listeners i.e. for logging purposes and just subscribe them to the inactive-user login-attempt event.

这篇关于Symfony2 FOSUserBundle - 针对“用户活动”进行验证国旗登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆