【问题标题】:Symfony2: user/authentication provider; password checkSymfony2:用户/身份验证提供者;密码检查
【发布时间】:2013-08-20 03:07:13
【问题描述】:

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

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

 return new WebserviceUser($username, $password, $salt, $roles);
  1. 问题是:为什么这里返回的是用户对象和密码。
  2. 问题:如何找回这个班级的密码?这不是身份验证提供者的任务吗?如果有,那里的密码怎么查?

这个模型肯定有一个用例有意义,但目前我还没有看到。也许这里有人有背景向我解释。

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

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

【问题讨论】:

    标签: php authentication symfony ldap


    【解决方案1】:

    安全系统确实不堪重负,很难知道从哪里开始。我怀疑那里可能已经有 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 服务对用户进行身份验证(绑定)。用户在登录表单中输入的明文密码可通过 $presentedPassword 获得。

    一旦您拥有经过身份验证的用户,事情就会变得有点模糊。您提到在本地数据库中缓存内容。您可能最终不得不重写 authenticationProvider.authenticate 方法以正确构建经过身份验证的令牌。你可能需要训练你的 userProvider.refreshUser 来和你的本地缓存对话。在进行 ldap 搜索之前,您甚至可能需要让 userProvider.loadUserByUsername 检查您的本地缓存。这些都是您的设计特有的细节。

    您可以使用参数密钥 security.authentication.provider.dao.class 从 form_login 防火墙中指向您自己的身份验证提供程序类。反过来,这将使您无需构建完整的防火墙包即可运行大部分(可能全部)ldap 功能。

    玩得开心。

    【讨论】:

    • 谢谢。这是我一直在寻找的解释。我知道我必须重写一些方法/类。之前存在的 LDAP 捆绑包一直在使用,根据我们的要求,它们将被替换为自己的捆绑包。
    • (Symfony 2.6) 一个问题,如果我使用的是 LoginModel(username, password) 和 LoginType(构建这些字段,命名会发生变化,你能告诉我如何获取用户名和密码...... ),在进入authenticateToken(TokenInterface $token,UserProviderInterface $userProvider,$providerKey)之前,请求将令牌存储在哪里,与symfony的约定(_username,_password)不同,在我的类中LdapAuthenticator实现了SimpleFormAuthenticatorInterface。谢谢。
    • @Felix - 最好开始一个新问题。我不明白你在问什么。
    • 在 symfony 2.0 中,如何覆盖 checkAuthentication 方法而不是使用 DaoAuthenticationProvider->checkAuthentication()
    猜你喜欢
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 2014-04-07
    • 2015-04-16
    • 2020-01-23
    • 2018-03-08
    • 1970-01-01
    相关资源
    最近更新 更多