设置角色Symfony 2安全性中的错误

时间:2015-08-21 00:29:15

标签: php symfony

我正在创建一个用户表单,其中通过表单下拉列表选择了角色。我的表单和实体看起来像这样

//entity

private $roles;
public function getRoles()
{

    return $this->roles;
}

//form

class RoleType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'choices' => array(
            'ROLE_USER' => 'ROLE_USER',
            'ROLE_ADMIN' => 'ROLE_ADMIN',
        )
    ));
}

public function getParent()
{
    return 'choice';
}

public function getName()
{
    return 'role';
}


class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('username')
        ->add('password', 'repeated', array(
            'type' => 'password',
            'invalid_message' => 'The password fields must match.',
            'options' => array('attr' => array('class' => 'password-field')),
            'required' => true,
            'first_options'  => array('label' => 'Password'),
            'second_options' => array('label' => 'Repeat Password'),
        ))
        //->add('terms', 'checkbox', array(
           // 'property_path' => 'termsAccepted',
       // ))
        ->add('firstname')
        ->add('lastname')
        ->remove('photo')
        ->add('email', 'email')
        ->remove('status')
        ->remove('createdBy')
        ->remove('isActive')
        ->remove('dateCreated')
        ->remove('updatedBy')
        ->remove('dateUpdated')
        //->remove('roles', 'choice', array(
           // 'choices' => array('ROLE_USER' => 'ROLE_USER', 'ROLE_ADMIN' => 'ROLE_ADMIN'),
        //))
        ->add('roles', new RoleType(), array(
            'placeholder' => 'Choose Roles',
        ))
        //->add('terms', 'checkbox', array(
          //  'property_path' => 'termsAccepted',
           // 'attr' => array('class' => 'checkbox'),
       // ))
        ->add('Register', 'submit')
    ;
}

public function getName()
{
    return 'registration';
}

创建一个通过表单下拉列表选择角色的用户时我没有问题。问题是,在登录期间,它会抛出错误,必须在数组中,而不是在字符串中

  

捕获致命错误:参数4传递给Symfony \ Component \ Security \ Core \ Authentication \ Token \ UsernamePasswordToken :: __ construct()必须是类型数组,字符串给定,在/ var / www /

中调用

我更改了我的用户实体

 private $roles = array();
 public function setRoles($roles)
{
    $this->roles = $roles;

    return $this;
}

 public function getRoles()
 {
   return array($this->roles);
 }

用户现在可以成功登录,但在以

形式添加其他用户时会引发错误
  

type" array"的值无法转换为有效的数组键。

这只是一个简单的用户包。我不想使用像FOSUsersrBundle这样的另一个第三方软件包。想知道如何解决这个问题吗?

更新

在控制器中,我用它将其存储到数据库中

public function createAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    //$form = $this->createForm(new RegistrationType(), new Registration());
    $form = $this->createForm(new RegistrationType(), new Users());

    $form->handleRequest($request);

    if ($form->isValid()) {
        $registration = new Users();
        $registration = $form->getData();
        $registration->setDateCreated(new \DateTime());
        //$registration->setRoles('ROLE_ADMIN');
        $registration->setPhoto('http://www.gravatar.com/avatar/'.md5(trim($request->get('email'))));
        $pwd=$registration->getPassword();
        $encoder=$this->container->get('security.password_encoder');
        $pwd=$encoder->encodePassword($registration, $pwd);
        $registration->setPassword($pwd);
        $em->persist($registration);
        $em->flush();

        $this->addFlash('danger', 'New User successfully added!');
        return $this->redirect($this->generateUrl('voters_list'));
    } else {
        $this->addFlash('danger', 'Some errors buddy cannot proceed, please check!');
        return $this->render('DuterteBundle:Security:register.html.twig',array(
            'form' => $form->createView())
        );
    }

更新

我的基本映射

Project\Bundle\DuterteBundle\Entity\Users:
type: entity
table: users
repositoryClass: Project\Bundle\DuterteBundle\Repository\UsersRepository
#indexes:
    #role_id_idx:
        #columns:
            #- role_id
id:
    id:
        type: integer
        nullable: false
        unsigned: false
        comment: ''
        id: true
        generator:
            strategy: IDENTITY
fields:
    username:
        type: string
        nullable: false
        length: 50
        fixed: false
        comment: ''
    password:
        type: string
        nullable: false
        length: 32
        fixed: false
        comment: ''
    firstname:
        type: string
        nullable: true
        length: 50
        fixed: false
        comment: ''
    lastname:
        type: string
        nullable: true
        length: 50
        fixed: false
        comment: ''
    photo:
        type: string
        nullable: true
        length: 200
        fixed: false
        comment: ''
    email:
        type: string
        nullable: true
        length: 200
        fixed: false
        comment: ''
    status:
        type: string
        nullable: true
        length: 8
        fixed: false
        comment: ''
    roles:
        type: string
        nullable: true
        length: 100
        fixed: false
        comment: ''

在mysql中,users表包含角色列,其中存储了角色,例如ROLE_USERS'" ROLE_ADMIN'等。从用户实体中更改getRoles函数

  public function getRoles()
  {
        return array('ROLE_USER'_)
  }

将成功记录用户,但角色始终设置为' ROLE_USERS'即使在数据库中,用户的角色也相当于' ROLE_ADMIN'

1 个答案:

答案 0 :(得分:5)

代码中最大的错误是在getRoles()函数中返回数组内的数组:

 private $roles = array();
 public function setRoles($roles)
 {
    $this->roles = $roles;
    return $this;
 }

 public function getRoles()
 {
   return array($this->roles);
 }

现在,在您的地图信息中,您将角色视为字符串,这意味着您的用户只使用一个角色,这简化了很多事情:

我们要更改字段的名称,因为安全组件需要一个数组并使用函数“getRoles()”,因为它继承自UserInterface或AdvancedUserInterfaceClass,但是如果已经存在数据,则表单检查对象在它上面(您还可以编辑和/或预加载要在表单中显示的数据),必须在数据库和映射信息中进行等效更改。

//entity
private $role;

public function setRole($role){
    $this->roles = $role;
    return $this;
}

public function getRole(){
    return $this->roles;
}

public function getRoles(){
    return array($this->role);
}

您不需要将其设置为数组,因为您将其作为字符串保留,安全组件不会注册用户,您可以这样做。为此,我们将改变你的formtypes和你的控制器。

//formtype
//I don't know what version you are using, but you dont need a separate formtype to add a choice and neither need to `remove` fields, you just don't `add` them.
//Remember to change the field in from 'roles' to 'role'
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('username')
        ->add('password', 'repeated', array(
            'type' => 'password',
            'invalid_message' => 'The password fields must match.',
            'options' => array('attr' => array('class' => 'password-field')),
            'required' => true,
            'first_options'  => array('label' => 'Password'),
            'second_options' => array('label' => 'Repeat Password'),
        ))
        ->add('firstname')
        ->add('lastname')
        ->add('email', 'email')
        ->add('role', 'choice', array(
            'choices' => array('ROLE_USER' => 'User', 'ROLE_ADMIN' => 'Admin'),
        ))
        ->add('Register', 'submit')
    ;
}

public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults(array(
        'data_class' => 'Project\Bundle\DuterteBundle\Entity\Users' //this is important
    ));
}
}

现在你的控制器:

//Controller
//Also if you link a form to a entity you dont need the `getData()`

use Project\Bundle\DuterteBundle\Entity\Users;

public function createAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $user = new Users();
    $form = $this->createForm(new RegistrationType(), $user);

    $form->handleRequest($request); //here, every form field that has an equivalent in the entity, fills the entity property instead, that's why you only need to set the role as a string ;)

    if ($form->isValid()) {
        $user->setDateCreated(new \DateTime());
        $user->setPhoto('http://www.gravatar.com/avatar/'.md5(trim($request->get('email'))));
        $pwd=$user->getPassword();
        $encoder=$this->container->get('security.password_encoder');
        $pwd=$encoder->encodePassword($user, $user->getPassword());
        $user->setPassword($pwd);
        $em->persist($user);
        $em->flush();

        $this->addFlash('danger', 'New User successfully added!');
        return $this->redirect($this->generateUrl('voters_list'));
    } else {
        $this->addFlash('danger', 'Some errors buddy cannot proceed, please check!');
        return $this->render('DuterteBundle:Security:register.html.twig',array(
            'form' => $form->createView())
        );
    }
}

你可以看到更简单,更容易和更干净。安全组件使用getRoles将角色加载到应用程序中,是一个数组,因为用户可以获得多个角色,但为此您需要一个不同的模式。