Symfony2 FOS用户密码检查回调约束


Symfony2 FOS User password check callback constraint

我在我创建的多站点平台上使用FOS User Bundle。我需要根据用户角色设置密码检查的自定义约束(对admin用户进行更强的regex检查)。

我如何以及在哪里可以安全地做到这一点?Assert/Constraint在User实体上似乎不可用,比如这个答案不允许对角色进行不同的检查。

谢谢你的回答,

尼古拉斯

您可以创建一个自定义验证约束,并将其附加到类而不是属性。

Acme ' ' UserBundle '验证器'约束PasswordForRoleRegex

namespace Acme'UserBundle'Validator'Constraints;
/**
 * @Annotation
 * @Target({"CLASS", "ANNOTATION"})
 */
class PasswordForRoleRegex extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}

Acme ' ' UserBundle '验证器'约束PasswordForRoleRegexValidator

namespace Acme'UserBundle'Validator'Constraints;
class PasswordForRoleRegexValidator extends ConstraintValidator
{
    const REGEX_SUPER_ADMIN = '/..../';
    // or an actual message if you don't use translations
    const MESSAGE_SUPER_ADMIN = 'acme.user.password.regex.super_admin';
    const REGEX_ADMIN = '/..../';
    const MESSAGE_ADMIN = 'acme.user.password.regex.admin';
    /// and so on
    const REGEX_NORMAL_USER = '/..../';
    const MESSAGE_NORMAL_USER = 'acme.user.password.regex.normal_user';

    public function validate($user, Constraint $constraint)
    {
        if (!$constraint instanceof PasswordForRoleRegex) {
            throw new UnexpectedTypeException($constraint, PasswordForRoleRegex::class);
        }
        if (!$user instanceof UserInterface) {
            throw new UnexpectedTypeException($user, UserInterface::class);
        }
        if (null === $password = $user->getPlainPassword()) {
            return;
        }
        if (preg_match($this->getPasswordRegexForUserRole($user), $password) {
            return;
        }
        $this->context->buildViolation($this->getErrorMessageForUserRole($user))
            ->atPath('plainPassword')
            ->addViolation();
    }
    /**
     * @param UserInterface $user
     * @return string
     */
    private function getPasswordRegexForUserRole(UserInterface $user)
    {
        if ($user->hasRole('ROLE_SUPER_ADMIN')) {
            return self::REGEX_SUPER_ADMIN;
        }
        if ($user->hasRole('ROLE_ADMIN')) {
            return self::REGEX_ADMIN;
        }
        // and so on
        return self::REGEX_NORMAL_USER;
    }
    /**
     * @param UserInterface $user
     * @return string
     */
    private function getErrorMessageForUserRole(UserInterface $user)
    {
        if ($user->hasRole('ROLE_SUPER_ADMIN')) {
            return self::MESSAGE_SUPER_ADMIN;
        }
        if ($user->hasRole('ROLE_ADMIN')) {
            return self::MESSAGE_ADMIN;
        }
        // and so on
        return self::MESSAGE_NORMAL_USER;
    }
}

可以在验证中使用,如…

Acme ' UserBundle ' '用户模型

namespace Acme'UserBundle'Model;
use Acme'UserBundle'Validator'Constraints'PasswordForRoleRegex;
use FOS'UserBundle'Model'User as BaseUser;
/**
 * @PasswordForRoleRegex(groups={"Registration", "ChangePassword", ....})
 */
class User extends BaseUser
{
    //...
}

或. .

@AcmeUserBundle/资源/config/validation.yml

Acme'UserBundle'Model'User:
    properties:
        Acme'UserBundle'Validator'Constraints'PasswordForRoleRegex:
            groups: ["Registration", "ChangePassword", ....]

或我懒得做的XML

I'm 非常确定这将工作,但它没有经过测试,所以它可能不是100%