2016-12-16 52 views
0

Heyo!Symfony Custom UserProvider Auth + Parse SDK

我知道这是一个常见的问题,人们在定制提供商和Web服务身份验证方面存在问题。我花了数小时试图找出如何做到这一点,但我几乎吓坏了。

所以,问题是:我正在使用Symfony防火墙以及自定义UserProvider和AbstractGuardAuthenticator。问题出在UserProvider实现中的loadUserByUsername($username)函数中。

出于安全原因,我无法从Parse(我的Web服务)中检索用户密码,并且loadUserByUsername($username)函数询问了这一点。即使在关于how to create a custom user provider using web services的文档中,他们也会从数据库中检索用户密码。

那么这种情况下的解决方案是什么?我无法访问用户密码时该怎么办?

我当前的代码是类似的东西:

$app['app.authenticator'] = function() { 
    return new Authenticator($app); 
}; 


$app['security.firewalls'] = array(
    'login' => array(
     'pattern' => '^/login/$', 
    ), 
    'secured' => array(
     'pattern' => '^.*$', 
     'form' => array('login_path' => '/login/', 'check_path' => '/login/auth/'), 
     'logout' => array('logout_path' => '/logout/', 'invalidate_session' => true), 
     'guard'   => array(
      'authenticators' => array(
       'app.authenticator' 
      ), 
     ), 
     'users' => function() use ($app) { 
      return new UserProvider($app); 
     }, 
    ) 
); 

的Authenticator.php是相当大的代码,因为扩展了AbstractGuardAuthenticator类。但我是来自Symfony文档的basically using this one。唯一的事情是我向UserProvider类发送用户名和密码,因为这样我可以检查用户和密码是否正确。就像这样:

public function getUser($credentials, UserProviderInterface $userProvider) { 
    return $userProvider->loadUserByUsername($credentials); 
} 

而且我UserProvider类是默认的,我只是loadUserByUsername函数内部检查,如果从我的身份验证的正在添加凭据是正确的。事情是这样的:

public function loadUserByUsername($credentials) { 
    $encoder = new BCryptPasswordEncoder(13); 

    try { 
     $user = ParseUser::logIn($credentials['username'], $credentials['password']); 
    } catch (ParseException $error) { 
     throw new UsernameNotFoundException(sprintf('Invalid Credentials.')); 
    } 

    return new User($credentials['username'], $encoder->encodePassword($credentials['password'], ''), explode(',', 'ROLE_USER'), true, true, true, true); 
} 

的问题是:在登录后(一切与登录工作正常),Silex的每一个需要固定页面调用loadUserByUsername功能,而只是发送用户名参数。

所以基本上,我不知道该怎么做家伙。我真的想弄清楚如何让这件事情起作用。

感谢您的帮助!

+0

这将有助于查看您的整个实施。你有一个自定义的认证和用户模型?如果你知道密码是正确的,你可以使用这个密码(为什么试图从ParseUser获得相同的密码?)和用户名来创建一个新的用户模型并返回它。 – Rawburner

+0

嘿@Rawburner,谢谢你的时间!我只是用一些代码更新了我的问题。让我知道现在更清楚。我正在使用默认的用户模型。那么,有什么方法可以在用户模型中保存密码并随时使用它?告诉我更多关于那个:-) –

回答

0

我有一个类似的实现,这个问题是众所周知的。在我的用户提供者中,我有loadUserByUsername($ username)和refreshUser(UserInterface $ user)方法。因为我有和你一样的问题,所以我不检查loadUserByUsername中的用户,但是简单地返回一个新对象,只有用户名才能打扰流。 loadUserByUsername对外部API没有意义,所以我简单地跳过它。 refreshUser方法要么在每个请求上调用,这是有用的。

在你的AbstractGuardAuthenticator中,你有方法createAuthenticatedToken,它返回一个标记。在那里,你应该有充分的authentificated用户:

abstract class AbstractGuardAuthenticator implements GuardAuthenticatorInterface 
{ 
    /** 
    * Shortcut to create a PostAuthenticationGuardToken for you, if you don't really 
    * care about which authenticated token you're using. 
    * 
    * @param UserInterface $user 
    * @param string  $providerKey 
    * 
    * @return PostAuthenticationGuardToken 
    */ 
    public function createAuthenticatedToken(UserInterface $user, $providerKey) 
    { 

     //do login stuff 
     //save password in user 

     return new PostAuthenticationGuardToken(
      $user, 
      $providerKey, 
      $user->getRoles() 
     ); 
    } 
} 

然后,我我就不会用loadUserByUsername但refreshUser代替。两者都在每次请求时被调用:

/** 
* Don't use 
* @codeCoverageIgnore 
* @param string $username 
* @return User 
*/ 
public function loadUserByUsername($username) 
{ 
    return new User($username, null, '', ['ROLE_USER'], ''); 
} 

/** 
* Refresh user on every subrequest after login 
* @param UserInterface $user 
* @return User 
*/ 
public function refreshUser(UserInterface $user) 
{ 

    $password = $user->getPassword(); 
    $username = $user->getUsername(); 
    //login check 
}