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でこれをsecured_areaの下に配置してみてください

username_parameter: username
password_parameter: password

多分それはあなたを助けます!

于 2012-04-13T03:51:48.400 に答える
0

これはかなり古いですが、私の答えが他の人に役立つことを願っています。

フォームコンポーネントとセキュリティコンポーネントの使用を混在させようとすると、まったく同じ問題が発生しました。

残念ながら、セキュリティ コンポーネントは login_check 関数を呼び出すときに、入力フォームの「名前」パラメーター (名前の HTML 定義) _usernameおよび_passwordに依存しているため、これは不可能です。これは、フォーム コンポーネントでは定義できません (input 要素のこのオプションのパラメーターを定義する方法はありません)。

要素に名前を付けるとき

->add('my_name',...

実際には、これは通知される要素の id パラメータであり、「name」パラメータではありません。buidlForm 関数によって与えられる「名前」は「somename[my_name]」 (somename は Form クラスの getName() 関数によって返される値) になり、セキュリティ コンポーネントで要求される「_username」にすることはできません。

おそらく1つの回避策は、セキュリティ定義ファイルでusername_parameterを「somename [my_name]」として定義して、コンポーネントがそれを探すことですが、これは非常に厄介なハックであるため、試したことはありません.

編集: 実際、私が別の問題に使用したもう 1 つの回避策は、フォーム クラスの getName() 関数で空の文字列を返すことです。したがって、"_username" と "_password" の値を name 属性に与えることができるかもしれません (まだ試していません)。

于 2013-06-04T17:15:28.273 に答える