0

从 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

4

1 回答 1

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 服务对用户进行身份验证(绑定)。用户在登录表单中输入的明文密码可通过 $presentedPassword 获得。

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

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

玩得开心。

于 2013-08-19T19:07:13.273 回答