Php ';不良凭证';Symfony 2中的自定义身份验证提供程序出错

Php ';不良凭证';Symfony 2中的自定义身份验证提供程序出错,php,authentication,symfony,forms-authentication,symfony-2.2,Php,Authentication,Symfony,Forms Authentication,Symfony 2.2,我正在使用Symfony 2开发一个web应用程序。更具体地说,多亏了Symfony手册的指导,我正在尝试创建一个自定义身份验证提供程序 我必须自定义身份验证提供程序,因为我不能将登录表单中输入的用户名和密码与数据库中存储的用户名和密码进行检查。但是,无论如何,这不是我的问题 问题是,阅读我的代码(粘贴在下面),任何人都应该能够登录并输入我数据库中已有的用户名,无论密码是否正确(与存储在数据库中的密码相比),因为我只检查输入的用户名是否存在于数据库中。 但事实并非如此:神奇的是,密码被检查了,当

我正在使用Symfony 2开发一个web应用程序。更具体地说,多亏了Symfony手册的指导,我正在尝试创建一个自定义身份验证提供程序

我必须自定义身份验证提供程序,因为我不能将登录表单中输入的用户名和密码与数据库中存储的用户名和密码进行检查。但是,无论如何,这不是我的问题

问题是,阅读我的代码(粘贴在下面),任何人都应该能够登录并输入我数据库中已有的用户名,无论密码是否正确(与存储在数据库中的密码相比),因为我只检查输入的用户名是否存在于数据库中。 但事实并非如此:神奇的是,密码被检查了,当我尝试使用错误的密码登录时,我会收到“坏凭据”错误消息

我粘贴我的代码。 我的应用程序/config/security.yml:

jms_security_extra:
    secure_all_services: false
    expressions: true

security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
        Epilille\UserBundle\Entity\User: plaintext

    role_hierarchy:
        ROLE_STUDENT:     ROLE_USER
        ROLE_AER:         ROLE_STUDENT
        ROLE_PROF:        ROLE_AER
        ROLE_ADMIN:       ROLE_PROF
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
                    student:  { password: studentpass, roles: ['ROLE_STUDENT'] }
                    mestag_a: { password: mestag_apass, roles: ['ROLE_AER'] }
        intra_provider:
            entity: { class: EpililleUserBundle:User, property: username }

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

        login:
            pattern:  ^/login$
            anonymous: true

        intra_secured:
            pattern:  ^/
            intra: true
            provider: intra_provider
            form_login:
              login_path: login
              check_path: login_check
              default_target_path: epilille_home_homepage
            logout:
                path:   logout
                target: login

    access_control:
        # - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY}
my UserBundle的体系结构:

.
├── Controller/
│   └── SecurityController.php
├── DataFixtures/
│   └── ORM/
│       └── Users.php
├── DependencyInjection/
│   ├── Configuration.php
│   ├── EpililleUserExtension.php
│   └── Security/
│       └── Factory/
│           └── IntraFactory.php
├── Entity/
│   ├── User.php
│   └── UserRepository.php
├── EpililleUserBundle.php
├── EpiLogin.class.php
├── Resources/
│   ├── config/
│   │   └── services.yml
│   ├── doc/
│   │   └── index.rst
│   ├── public/
│   │   ├── css/
│   │   ├── images/
│   │   └── js/
│   ├── translations/
│   │   └── messages.fr.xlf
│   └── views/
│       ├── layout.html.twig
│       └── User/
│           └── login.html.twig
└── Security/
    ├── Authentication/
    │   ├── Provider/
    │   │   └── IntraProvider.php
    │   └── Token/
    │       └── IntraUserToken.php
    ├── Firewall/
    │   └── IntraListener.php
    └── User/
        └── IntraUserProvider.php
我的工厂:

<?php

namespace       Epilille\UserBundle\DependencyInjection\Security\Factory;

use         Symfony\Component\DependencyInjection\ContainerBuilder;
use         Symfony\Component\DependencyInjection\Reference;
use         Symfony\Component\DependencyInjection\DefinitionDecorator;
use         Symfony\Component\Config\Definition\Builder\NodeDefinition;
use         Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;

class           IntraFactory implements SecurityFactoryInterface
{
  public function   create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
  {
    $providerId = 'security.authentication.provider.intra.'.$id;
    $container
      ->setDefinition($providerId, new DefinitionDecorator('intra.security.authentication.provider'))
      ->replaceArgument(0, new Reference($userProvider))
      ;

    $listenerId = 'security.authentication.listener.intra.'.$id;
    $listener = $container->setDefinition($listenerId, new DefinitionDecorator('intra.security.authentication.listener'));

    return array($providerId, $listenerId, $defaultEntryPoint);
  }

  public function   getPosition()
  {
    return 'pre_auth';
  }

  public function   getKey()
  {
    return 'intra';
  }

  public function   addConfiguration(NodeDefinition $node)
  {
  }
}
如果我这样改变它:

public function       supports(TokenInterface $token)
{
  return $token instanceof IntraUserToken;
}
public function       supports(TokenInterface $token)
{
  return (true);
}
与我输入一个好的用户名(不管密码是什么)的情况有所不同:我经过身份验证,分析器现在说我使用的是令牌类“IntraUserToken”(这似乎正是我想要的)

因此,我的问题是:

  • 为什么我的身份验证解决方案不能与IntraProvider::supports方法的第一个版本一起使用
  • 为什么每次在IntraProvider::supports方法中返回true时它都有效
在食谱中,他们像我在这个方法的第一个版本中那样做,所以我不认为每次都返回true是个好主意,是吗


我希望我把我的问题说清楚,谢谢你的时间和回答

Symfony安全组件迭代提供程序并检查哪个提供程序支持给定的令牌。似乎您得到了除IntaUserToken之外的其他令牌,并且使用了其他提供程序。。。真的很奇怪,你能检查一下你在support method中有什么令牌吗?@l3l0[对不起,我很久以前就回答了,但我刚刚知道如何通知你我已经回答了你的评论]。因此,我在IntraProvider::supports方法中打开了一个文件,在其中写入参数中包含的令牌:$token:Epilille\UserBundle\Security\Authentication\token\IntraUserToken$token:Symfony\Component\Security\Core\Authentication\token\UsernamePasswordToken该方法似乎被调用了两次,一次使用IntraUserToken,另一次使用UsernamePasswordToken。。。
<?php

namespace       Epilille\UserBundle\Security\Firewall;

use         Symfony\Component\HttpFoundation\Response;
use         Symfony\Component\HttpKernel\Event\GetResponseEvent;
use         Symfony\Component\Security\Http\Firewall\ListenerInterface;
use         Symfony\Component\Security\Core\Exception\AuthenticationException;
use         Symfony\Component\Security\Core\SecurityContextInterface;
use         Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use         Epilille\UserBundle\Security\Authentication\Token\IntraUserToken;
use         Epilille\UserBundle\Security\Authentication\Provider\IntraProvider;

class           IntraListener implements ListenerInterface
{
  protected     $securityContext;
  protected     $authenticationManager;

  public function   __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager)
  {
    $this->securityContext = $securityContext;
    $this->authenticationManager = $authenticationManager;
  }

  public function   handle(GetResponseEvent $event)
  {
    // I have to do this check because it seems like this function is called several times and if
    // it's not the first time, it will try to reset a new IntraUserToken with _username and _password not set.
    if ($this->securityContext->getToken()) {
      return;
    }

    $request = $event->getRequest();

    $token = new IntraUserToken();
    $token->setUser($request->get('_username'));
    $token->password = $request->get('_password');

    try {
      $authToken = $this->authenticationManager->authenticate($token);

      $this->securityContext->setToken($authToken);
    } catch (AuthenticationException $failed) {
      // ... you might log something here

      // To deny the authentication clear the token. This will redirect to the login page.
      $this->securityContext->setToken(null);
      return;

      // Deny authentication with a '403 Forbidden' HTTP response
      /* $response = new Response(); */
      /* $response->setStatusCode(403); */
      /* $event->setResponse($response); */
    }
  }
}
public function       supports(TokenInterface $token)
{
  return $token instanceof IntraUserToken;
}
public function       supports(TokenInterface $token)
{
  return (true);
}