Symfony2:用户/身份验证提供程序;密码检查

时间:2013-08-19 12:00:28

标签: php authentication symfony ldap

在Symfony的文档中,我了解用户提供程序和身份验证提供程序应该如何工作。我尝试实现自己的用户和/或身份验证提供程序。我还没有完全得到的,是如何比较/在这个系统中检查密码的位置。

在文档[1]中,我可以看到,如果用户存在,则用户提供者应返回用户对象。但是,我可以看到,如果找到了用户,则该示例中的用户将返回

 return new WebserviceUser($username, $password, $salt, $roles);
  1. 问题是:为什么在这里返回带有密码的用户对象。
  2. 问题:如何在此课程中检索密码?这不是身份验证提供程序的任务吗?如果是的话,如何在那里检查密码?
  3. 肯定有一个用例,这个模型有意义,但暂时,我没有看到它。也许这里有人有背景向我解释。

    背景:我想使用LDAP进行身份验证。所以我的第一种方法是创建一个用户提供程序,匿名检查用户是否通过ldap搜索存在,如果是,则尝试对他进行身份验证。问题是,我无法返回带有密码的用户对象(还有其他属性,我只有在用户已经过身份验证时才能获得)。然后,用户将被存储/缓存在本地数据库中,其中还将保存用户特定的设置和属性。

    [1] http://symfony.com/doc/current/cookbook/security/custom_provider.html#create-a-user-provider

1 个答案:

答案 0 :(得分:3)

安全系统确实令人难以招架,而且很难知道从哪里开始。我怀疑那里可能已经有ldap捆绑(提示),但制作自己的捆绑包更有趣。

了解标准form_login防火墙的实现方式很有帮助。身份验证提供程序仅减少为两种方法:

namespace Symfony\Component\Security\Core\Authentication\Provider;

class DaoAuthenticationProvider extends UserAuthenticationProvider
{
    private $encoderFactory;
    private $userProvider;

protected function retrieveUser($username, UsernamePasswordToken $token)
{
    try {
        $user = $this->userProvider->loadUserByUsername($username);

protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
       if (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) {
            throw new BadCredentialsException('The presented password is invalid.');

因此,提交了一个登录表单,用户填写用户名和密码,按下登录按钮,form_login防火墙拦截login_check请求,执行各种奇妙的操作,但最终调用authenticationProvider.retrieverUser,后者又调用userProvider .loadUserByUsername。

然后,您的ldap用户提供商将对用户名执行ldap搜索。如果找不到任何内容,则抛出UserNotFoundException。如果找到了用户,那么您将包装任何有用的信息位并返回用户对象。此时密码无关紧要。

更多魔法发生,最终使用用户提供程序返回的任何用户对象调用authenticationProvider.checkAuthentication。此时,您将使用ldap服务对用户进行身份验证(绑定)。用户在登录表单中键入的明文密码可通过$ presentPassword获得。

一旦有了经过身份验证的用户,那么事情就会变得有些模糊。您在本地数据库中提到了缓存内容。您可能最终必须覆盖authenticationProvider.authenticate方法以正确构建经过身份验证的令牌。您可能需要训练您的userProvider.refreshUser与您的本地缓存进行通信。在执行ldap搜索之前,您甚至可能需要让userProvider.loadUserByUsername检查本地缓存。这些都是您设计的具体细节。

您可以使用参数键security.authentication.provider.dao.class从form_login防火墙内指向您自己的身份验证提供程序类。这反过来会让你运行大部分(可能全部)你的ldap功能而无需构建完整的防火墙软件包。

玩得开心。