2015-04-21 53 views
0

我正在创建自定义身份验证提供程序。我写了我自己的身份验证提供程序,侦听程序,令牌和所有内容。它基于表单登录,并且我已经遍历代码,并且所有内容似乎都已正确配置。一切都按正确的顺序调用,并且我的身份验证提供程序被完美调用。身份验证提供程序成功验证用户身份,并返回经过身份验证的令牌。我扩展了AbstractAuthenticationListener其中,在句柄方法中,将设置安全上下文。Symfony自定义身份验证提供程序 - 用户未完全登录(登录,未验证)

用户似乎已经登录,但在调试工具栏中,令牌未设置,我看到“您未通过身份验证”和“无令牌”。

是否有我缺少的配置设置?为什么用户会登录,身份验证提供程序成功返回,具有已验证的令牌,在安全上下文中设置但仍未验证?有关如何调试的任何提示?

(如果需要,我将发布的代码。)

编辑:令牌定义:

这是很简单的,从AbstractToken只是延长:

class UserToken extends AbstractToken 
{ 
    private $username; 
    private $password; 
    private $domain; 
    private $providerKey; 

    public function __construct($username, $password, $domain, $provider_key, array $roles = array('ROLE_USER')) 
    { 
     parent::__construct($roles); 
     $this->username = $username; 
     $this->password = $password; 
     $this->domain = $domain; 
     $this->providerKey = $provider_key; 

    } 

    public function getCredentials() 
    { 
     return ''; 
    } 

    function getUsername() { 
     return $this->username; 
    } 

    function getDomain() { 
     return $this->domain; 
    } 
    function getPassword() { 
     return $this->password; 
    } 

    function getProviderKey(){ 
     return $this->providerKey; 
    } 
} 

验证监听器:

class Listener extends AbstractAuthenticationListener 
{ 
    protected $authenticationManager; 

    public function __construct(
     SecurityContextInterface $securityContext, 
     AuthenticationManagerInterface $authenticationManager, 
     SessionAuthenticationStrategyInterface $sessionStrategy, 
     HttpUtils $httpUtils, 
     $providerKey, 
     AuthenticationSuccessHandlerInterface $successHandler, 
     AuthenticationFailureHandlerInterface $failureHandler, 
     array $options = array(), 
     LoggerInterface $logger = null, 
     EventDispatcherInterface $dispatcher = null 
     //CsrfProviderInterface $csrfProvider = null 
    ) { 

     parent::__construct(
      $securityContext, 
      $authenticationManager, 
      $sessionStrategy, 
      $httpUtils, 
      $providerKey, 
      $successHandler, 
      $failureHandler, 
      array_merge(
      array(
       'username_parameter' => '_username', 
       'password_parameter' => '_password', 
       'domain_parameter' => '_domain', 
       'csrf_parameter' => '_csrf_token', 
       'intention' => 'authenticate', 
       'post_only' => true, 
      ), 
      $options 
     ), 
      $logger, 
      $dispatcher 
     ); 

    } 

    /** 
    * Performs authentication. 
    * 
    * @param Request $request A Request instance 
    * 
    * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response 
    * 
    * @throws AuthenticationException if the authentication fails 
    */ 
    protected function attemptAuthentication(Request $request) 
    { 
     // Create initial unauthenticated token and pass data to the authentication manager. 
     // TODO validate request data. 
     $username = trim($request->request->get($this->options['username_parameter'], null, true)); 
     $password = $request->request->get($this->options['password_parameter'], null, true); 
     $domain = $request->request->get($this->options['domain_parameter'], null, true); 
     $token = $this->authenticationManager->authenticate(new UserToken($username, $password, $domain, $this->providerKey)); 
     return $token; 
    } 
} 

上述代码将调用提供的auth函数通过的AuthenticationManager R:

//This is from the AuthenticationProvider 
public function authenticate(TokenInterface $token) { 
    $loginHandler = new LoginAuthenticationHandler($token->getUsername(), $token->getPassword(), $token->getDomain()); 
//This code just calls our web service and authenticates. I removed some business logic here, but this shows the gist of it. 
    if(!$boAuthenticationToken = $loginHandler->authenticate()) 
    { 
     throw new AuthenticationException('Bad credentials'); 
    } 
    else{ 
     $user = $this->userProvider->loadUserByUsername($token->getUsername()); 
     //$user = $this->userProvider->getUser($token, $boAuthenticationToken); 

     // Set the user which will be invoked in the controllers. 
     $token->setUser($user); 
     $token->setAuthenticated(true); 
     return $token; 
    } 
} 

捆绑Services.yml

parameters: 

services: 
    ws.security.authentication.provider: 
     #http://blog.vandenbrand.org/2012/06/19/symfony2-authentication-provider-authenticate-against-webservice/ 
     class: Aurora\OurCustomBundle\Security\Authentication\Provider\Provider 
     arguments: ["bo_remove_this_with_bo_auth_service", "", "@security.user_checker", "", "@security.encoder_factory"] 

    ws.security.authentication.listener: 
     class: Aurora\OurCustomBundle\Security\Firewall\Listener 
     parent: security.authentication.listener.abstract 
     abstract: true 
     #arguments: [] 
     arguments: ["@security.context", "@security.authentication.manager", "@security.authentication.session_strategy", "@security.http_utils", "ws.user_provider", "@security.authentication.customized_success_handler", "@main.cas.rest.user.authentication.failure.service"] 


    ws.user_provider: 
     class: Aurora\OurCustomBundle\Security\User\UserProvider 

最后,在UserProvider

class UserProvider implements UserProviderInterface 
{ 
    public function loadUserByUsername($username) 
    { 
     //Just return a simple user for now. 
     return new User($username, array('ROLE_USER')); 
    } 

    public function refreshUser(UserInterface $user) 
    { 
     if (!$user instanceof User) { 
      throw new UnsupportedUserException(
       sprintf('Instances of "%s" are not supported.', get_class($user)) 
      ); 
     } 

     return $this->loadUserByUsername($user->getUsername()); 
    } 

    public function supportsClass($class) 
    { 
     return $class === 'Aurora\OurCustomBundle\Security\User\User'; 
    } 
} 
+0

只是想法。检查您的登录用户是否有任何角色。你可以在profiler中做到这一点。 – kba

+0

这味道像一个令牌问题。你可以发布你的令牌服务定义吗? – pcm

+0

@kba:我查看了剖析器,似乎用户没有登录。在配置文件的安全部分,它只是说“没有令牌”。 – Foo

回答

0

多小时的揪头发后,我想通了这个问题!

令牌实现不正确。由于我实现了自己的Token,它从AbstractToken扩展而来,我还需要实现serialize()和unserialize()函数。

一旦我这样做,代码工作。更新的令牌类下面供将来参考:

class UserToken extends AbstractToken 
{ 
    private $username; 
    private $password; 
    private $domain; 
    private $providerKey; 

    public function __construct($username, $password, $domain, $provider_key, array $roles = array('ROLE_USER')) 
    { 
     parent::__construct($roles); 
     $this->username = $username; 
     $this->password = $password; 
     $this->domain = $domain; 
     $this->providerKey = $provider_key; 

    } 

    public function getCredentials() 
    { 
     return ''; 
    } 

    function getUsername() { 
     return $this->username; 
    } 

    function getDomain() { 
     return $this->domain; 
    } 
    function getPassword() { 
     return $this->password; 
    } 

    function getProviderKey(){ 
     return $this->providerKey; 
    } 

    function serialize(){ 
     return serialize(array($this->username, $this->password, $this->domain, parent::serialize())); 
    } 

    function unserialize($serialized){ 
     list($this->username, $this->password, $this->domain, $parentSerialization) = unserialize($serialized); 
     parent::unserialize($parentSerialization); 
    } 
}