2015-04-21 76 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); 
    } 
}