0

这是我的实体:

<?php

namespace Trade\TradeBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass = "Trade\TradeBundle\Repository\UserRepository")
 * @ORM\Table(name = "user")
 * @UniqueEntity(fields = "username", message = "The username already exists.")
 */
class User implements UserInterface
{
/**
 * @ORM\id
 * @ORM\Column(name = "id", type = "integer")
 * @ORM\GeneratedValue(strategy = "AUTO")
 */
protected $id;

/**
 * @ORM\Column(name = "username", type = "string", length = 20, unique = true)
 *
 * @Assert\NotBlank(
 *      message = "The username cannot be blank."
 * )
 */
protected $username;

/**
 * @ORM\Column(name = "password", type = "string", length = 40)
 *
 * @Assert\NotBlank(
 *      message = "The password cannot be blank."
 * )
 * @Assert\MinLength(
 *      limit = 8,
 *      message = "The password '{{ value }}' is too short. It should have {{ limit }} characters or more."
 * )
 * @Assert\MaxLength(
 *      limit = 16,
 *      message = "The password '{{ value }}' is too long. It should have {{ limit }} characters or less."
 * )
 */
protected $password;

/**
 * @ORM\Column(type = "string", length = 40)
 */
protected $salt;

public function __construct()
{
    $this->salt = md5(uniqid(null, true));
}

/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set username
 *
 * @param string $username
 */
public function setUsername($username)
{
    $this->username = $username;
}

/**
 * Get username
 *
 * @return string
 */
public function getUsername()
{
    return $this->username;
}

/**
 * Set password
 *
 * @param string $password
 */
public function setPassword($password)
{
    $this->password = $password;
}

/**
 * Get password
 *
 * @return string
 */
public function getPassword()
{
    return $this->password;
}

public function getSalt()
{
    return $this->salt;
}

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

public function eraseCredentials()
{
}

public function equals(UserInterface $user)
{
    return $this->username === $user->getUsername();
}
}

这是我的存储库:

<?php

namespace Trade\TradeBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * UserRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
    return $this->getEntityManager()->findOneByUsername($username);
}

public function refreshUser(UserInterface $user)
{
    return $this->loadUserByUsername($user->getUsername());
}

public function supportsClass($class)
{
    return $class === 'Trade\TradeBundle\Entity\User';
}
}

这是security.yml:

security:
    encoders:
        Trade\TradeBundle\Entity\User:
            algorithm: sha1
            encode_as_base64: false
            iterations: 1

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

providers:
    main:
        entity: { class: TradeTradeBundle:User, property: username }

firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false

    secured_area:
        pattern:    ^/
        form_login:
            check_path: /account/signin_check
            login_path: /account/signin
        logout:
            path:   /account/signout
            target: /
        anonymous: ~

access_control:
    - { path: ^/account/signin, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/account, roles: ROLE_USER }
    - { path: ^/admin, roles: ROLE_ADMIN }

这是我的控制器动作:

/**
 * @Route("/account/signin", name = "account_signin")
 * @Route("/account/signin_check", name = "account_signin_check")
 * @Method({"GET", "POST"})
 */
public function signInAction()
{
    $request = $this->getRequest();
    $session = $request->getSession();

    $user = new \Trade\TradeBundle\Entity\User();
    $form = $this->createForm(new \Trade\TradeBundle\Form\Type\UserType(), $user);

    if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR))
    {
        $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
    }
    else
    {
        $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
        $session->remove(SecurityContext::AUTHENTICATION_ERROR);
    }

    return $this->render('TradeTradeBundle:Account:signin.html.twig', array('form' => $form->createView(), 'error' => $error));
}

这是我的表单类:

<?php

namespace Trade\TradeBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;


class UserType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
    $builder->add('username', 'text', array('required' => false));
    $builder->add('password', 'password', array('required' => false));
}

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

public function getDefaultOptions(array $options)
{
    return array(
        'data_class' => 'Trade\TradeBundle\Entity\User'
    );
}
}

这是我的表格:

{% if error %}
    <div class="alert alert-error">{{ error }}</div>
{% endif %}
<form action="{{ path('account_signin_check') }}" method="post" class="form-inline" novalidate>
    <table class="table">
        <tr>
            <td style="width: 120px;">{{ form_label(form.username) }} <span class="required">*</span></td>
            <td style="width: 220px;">{{ form_widget(form.username, { 'attr': {'placeholder': 'Username'} }) }}</td>
            <td class="form-error" id="email_error">{{ form_errors(form.username) }}</td>
        </tr>
        <tr>
            <td>{{ form_label(form.password) }} <span class="required">*</span></td>
            <td>{{ form_widget(form.password, { 'attr': {'placeholder': 'Password'} }) }}</td>
            <td class="form-error" id="password_error">{{ form_errors(form.password) }}</td>
        </tr>
        <tr>
            <td colspan="2" style="text-align: right;">
                {{ form_rest(form) }}
                <input type="reset" value="Cancel" class="btn" />
                <input type="submit" value="Sign in" class="btn btn-danger" />
            </td>
        <td>&nbsp;</td>
        </tr>
    </table>
</form>

当我尝试登录时,会显示 BadCredentialsException。我不知道为什么。我想我根据 Symfony 的文档做的一切都是正确的,请帮忙。

4

2 回答 2

1

尝试使用 _username 和 _password 之类的输入名称,或者在您的 security.yml 中尝试将其放在 secure_area 下

username_parameter: username
password_parameter: password

也许它可以帮助你!

于 2012-04-13T03:51:48.400 回答
0

这已经很老了,但我希望我的回答可以帮助其他人。

我在尝试将表单组件的使用与安全组件混合使用时遇到了完全相同的问题。

不幸的是,这是不可能的,因为安全组件在调用 login_check 函数时依赖于输入表单“名称”参数(名称的 html 定义) _username_password 。不能用表单组件定义(无法定义输入元素的这个可选参数)。

当给元素命名时

->添加('我的名字',...

实际上,这是通知元素的 id 参数,而不是“名称”参数。buidlForm 函数给出的“name”将是“somename[my_name]”(其中 somename 是 Form 类的 getName() 函数返回的值),不能是安全组件要求的“_username”。

也许一种解决方法是在安全定义文件中将 username_parameter 定义为“somename [my_name]”,以便组件查找它,但我什至没有尝试过,因为这是一个非常讨厌的 hack。

编辑:实际上我用于另一个问题的另一种解决方法是在 Form 类的 getName() 函数中返回一个空字符串,因此我们得到:“my_name”作为输入元素属性,而不是“somename [my_name]”。所以也许我们可以尝试将“_username”和“_password”值赋予名称属性(没有尝试过)。

于 2013-06-04T17:15:28.273 回答