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


Symfony2: user/authentication provider; password check

在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

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

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

您可以使用参数密钥security.authenticationprovider.dao.class从form_login防火墙中指向您自己的身份验证提供程序类。这样一来,您就可以运行大部分(可能是所有)ldap功能,而无需构建一个完整的防火墙包。

玩得开心。