2015-11-15 6 views
2

Я следую рецептам книги и кулинарной книги Symfony, и я встретил проблему с простой формой входа - независимо от того, введен ли логин/пароль, появляется сообщение - «Недействительные учетные данные». Пользователи загружаются через Doctrine (пользовательский класс, который реализует UserInterface). Исходные коды: ФайлФорма входа в систему - Symfony 2.7

Безопасность:

providers: 
    user_provider: 
     entity: 
     class: BakaMainBundle:User 

firewalls: 

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

    default: 
     anonymous: ~ 
     http_basic: ~ 
     provider: user_provider 
     form_login: 
      login_path: /login 
      check_path: /login_check 
      target_path_parameter: /index/welcome 

access_control: 
    - { path: ^/admin, roles: ROLE_ADMIN } 

encoders: 
    Baka\MainBundle\Entity\User: 
    algorithm: bcrypt 
    cost: 12 

Контроллер:

class SecurityController extends Controller 
{ 
    /** 
    * @Route("/login", name="login_route") 
    */ 
    public function loginAction() 
    { 
     $authUtils = $this->get('security.authentication_utils'); 
     $error = $authUtils->getLastAuthenticationError(); 
     $enteredUsername = $authUtils->getLastUsername(); 

     return $this->render('BakaMainBundle::Login.html.twig', 
      array 
      (
       'last_username' => $enteredUsername, 
       'error' => $error, 
       'site' => 'login' 
      )); 
    } 

    /** 
    * @Route("/login_check", name="login_check") 
    */ 
    public function loginCheckAction() 
    { 

    } 
} 

хранилище пользователя:

class UserRepository extends \Doctrine\ORM\EntityRepository implements UserProviderInterface 
{ 
    public function loadUserByUsername($username) 
    { 
     $user = $this->createQueryBuilder('u') 
      ->where('u.username = :username OR u.email = :email') 
      ->setParameter('username', $username) 
      ->setParameter('email', $username) 
      ->getQuery() 
      ->getOneOrNullResult(); 

     if ($user === null) 
     { 
      $returnMessage = sprintf(
       '%s - such username of email adress does not exist in database! Try again with other login data.', 
       $username); 
      throw new UnsupportedUserException($returnMessage); 
     } 

     return $user; 
    } 

    public function refreshUser(UserInterface $user) 
    { 
     $userClass = get_class($user); 
     if (!$this->supportsClass($userClass)) 
     { 
      throw new UnsupportedUserException 
      (sprintf('Ops! Something goes wrong. Your user class is not supported by security system.')); 
     } 

     return $this->find($user->getId()); 
    } 

    public function supportsClass($userclass) 
    { 
     return $this->getEntityName() === $userclass || is_subclass_of($userclass, $this->getEntityName()); 
    } 

И форма HTML тег:

<form action="{{ path('login_check') }}" method="post"> 

Любые предложения? Буду признателен за решение моей проблемы.

+0

Я хотел бы добавить, что Symfony на самом деле даже не ссылается на мой метод UserRepository: loadUserByUsername ($ username) и запрос к БД. Это, наверное, главная проблема. – baka1408

ответ

1

Я думаю, вы должны использовать пространство имен классов вместо имени связки при указании класса поставщика. Кроме того, необходимо указать, какие property вы будете выбирать в качестве «имя пользователя» из вашего Entity:

security: 
    providers: 
     user_provider: 
      entity: 
      class: Baka\MainBundle\Entity\User 
      property: username (this should be an existing property of your entity class) 

Кроме того, ваш User объект должен реализовать Symfony\Component\Security\Core\User\UserInterface (или AdvancedUserInterface). Как только вы закончите с этим, все должно работать, если у вас есть пользователи в базе данных с правильно закодированным паролем.

Вы должны прочитать:

  1. How to Load Security Users from the Database (the Entity Provider) понять, как загружать пользователей из базы данных
  2. Security, чтобы получить лучшее понимание того, как компонент работы безопасности и как он должен быть настроен.
+0

Я прочитал обе статьи, которые вы упомянули и сделали точно так же, как они предполагали. Свойство: <имя_файла> не входит в мой код из-за использования пользовательского репозитория, который реализует UserProviderInterface - «Чтобы закончить это (репозиторий пользователей, который обрабатывает ввод электронной почты или логин вместо обычного входа), просто удалите ключ свойства от поставщика пользователя в security.yml «. Можно ли явно указать этот класс репозитория в security.yml? Переход к пространству имен классов тоже не изменился. – baka1408

+0

Вам нужно указать репозиторий в 'Entity'. Чтобы посмотреть, как это сделать, официальная документация доктрины [здесь] (http: //doctrine-orm.readthedocs.орг/проекты/Доктрина-ОРМ/о/последняя/ссылка/рабочий-с objects.html # таможенно-репозитории). Если у вас нет 'repositoryClass', установленного в вашей' Entity', это может быть причиной вашей проблемы. – tftd

+0

Да, это уже указано в Entity - "@ORM \ Entity (repositoryClass =" Baka \ MainBundle \ Entity \ UserRepository ")", но symfony вообще не вызывает метод DB запроса из репозитория. – baka1408

0

Я уже определил причину вопроса, и выяснилось, тривиальным - поле, которое служит в качестве закодированного пароля строки в БД были длиной 15 символов предел:

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

И поскольку 'Bcrypt '12 rounds' требует гораздо больше цифр для представления простого пароля, Doctrine была вынуждена сократить зашифрованный проход, поэтому позже его невозможно было расшифровать. После изменения предложенного размера Symfony проблема не исчезла:

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

Благодарим за поддержку.

+0

На самом деле вам не нужно столько символов в столбце. Обычно я устанавливаю мой на 255, хотя с 'bcrypt' мне не нужно больше 60. Вы можете проверить [this] (http://stackoverflow.com/a/5882472/393805) ответ для справки. – tftd

Смежные вопросы