如何在Symfony2的表单构建器中检查用户角色?

13

好的,我试图检查一个用户是否具有特定的角色,我参考了这个链接。

然而,当我执行以下代码:

public function buildForm(FormBuilder $builder, array $options)
{
    $builder
        ->add('nombre',null,array('label' => 'Usuario'))
        ->add('email')
        ->add('password', 'repeated', array(
            'type' => 'password',
            'invalid_message' => 'Los campos deben coincidir',
            'first_name' => 'password',
            'second_name' => 'confirmar password',
            'options' => array('required' => false)
            ))

        ->add('cliente', 'entity', array(
        'class' => 'ClientesBundle:Cliente',
        'empty_value' => 'Company',            
        'required'    => false,
        'empty_data'  => null)
    **)**
      $user = $this->securityContext->getToken()->getUser();
      **if ($user->getRol() == 'ROLE_SUPER_ADMIN'){**
        ->add('rol') 
        **}**
    ;

}

我也尝试了这个:

 **if ($this->securityContext->getToken()->getUser()->getRol() === 'ROLE_SUPER_ADMIN'){**
            ->add('rol') 
            **}**

**粗体的行(带有红色小线)表示有错误,错误信息为“unexpected if...”,我该如何修复?**

4个回答

17

你需要从控制器将用户对象传递给表单构建器。

$form = $this->createForm(
    new YourType(), 
    $data, 
    array('user' => $this->getUser())
);

然后在表单构建器中,您可以从$options中获取它:

public function buildForm(FormBuilder $builder, array $options)
{
    $user = $options['user']
}

别忘了在setDefaultOptions()中添加user索引:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        ...
        'user' => null
    ));
}

这就是我一直在寻找的! - Oyeme
2
对于SF3,请使用:public function configureOptions(OptionsResolver $resolver),而不是setDefaultOptions(OptionsResolverInterface $resolver) - Wesley Abbenhuis

16

如果将表单类型声明为服务,则可以在类中注入令牌存储。

因此,您可以在services.yml中这样声明服务:

my_form:
    class: AppBundle\Services\MyFormType
    public: true
    arguments:  ['@security.token_storage']

表单类是这样的:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class MyFormType extends AbstractType
{
    protected $tokenStorage;

    public function __construct(TokenStorage $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $user = $this->tokenStorage->getToken()->getUser();
        // Use the user object to build the form
    }
}

这是使用Symfony的方法!始终使用依赖注入。 - Thomas Decaux
在Symfony 3.4中,我必须在services.yml中添加标签:[form.type]。 - Gautier

8

我知道这是一个旧问题,但我想提出一个更好的替代方案来检查表单类型中的角色。

问题

使用TokenInterface和User对象的问题是它不会检查继承。例如,考虑以下security.yml

security:
    role_hierarchy:
        ROLE_ADMIN: ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

如果您的用户具有ROLE_SUPER_ADMIN,但没有将ROLE_ADMIN添加到其角色中,则上述解决方案将失败(如果您使用$user->hasRole('ROLE_ADMIN')),因为用户没有明确分配ROLE_ADMIN给他们的用户,并且hasRole()不会检查层次结构。

解决方案

使用AuthorizationCheckerInterface来获取isGranted()函数的访问权限。

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

class MyFormType extends AbstractType {

    protected $auth;

    public function __construct(AuthorizationCheckerInterface $auth) {
        $this->auth = $auth;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        
        // ...
        
        if($this->auth->isGranted('ROLE_ADMIN')) {
            // Do the thing here
        }
    }
}

这将尊重在security.yml中定义的任何层次结构。如果我们使用与上述相同的yml文件,当用户的配置文件中分配了ROLE_SUPER_ADMIN但没有分配ROLE_ADMIN时,$auth->isGranted('ROLE_ADMIN')将返回true。

关于Symfony 5及以上版本的更新

之前的解决方案在Symfony 5及以上版本仍然有效,但是根据Symfony 5的建议,可以进行一些微调。

现在更推荐使用Security而不是AuthorizationCheckerInterface,如果使用PHP 8,还可以使用构造函数提升

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Security;

class MyFormType extends AbstractType {

    public function __construct(protected Security $security) {
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
            
        // ...
            
        if($this->security->isGranted('ROLE_ADMIN')) {
            // Do the thing here
        }
    }
}

1

我成功地在Symfony 3.4中完成了这件事,而不需要传递到服务。我知道我的方法可能不是最专业的,但它很简单并且有效。

首先,从您的控制器将用户发送到您的表单类型。

$form = $this->get('form.factory')->create(addPlanExpectedType::class, $business,
            array('user' => $this->getUser())
        );

其次,恢复角色,并验证此$roles数组中是否存在"ROLE_ADMIN"。
public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $businessId = $options['data']->getId();

        $user = $options['user'];
        $roles = $user->getRoles();

        $boolAdmin = in_array('ROLE_ADMIN', $roles);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接