我正在使用fr3d/ldap-bundle
。如果他们不在db中,它会将我登录并从AD导入用户。没关系。
尽管AD用户我也有本地用户,这些用户都在我的数据库中。有一个特殊的列authType
,它说明了如何通过LDAP或本机(FOS)对用户进行身份验证。我已经创建了自己的用户提供商:
public function chooseProviderForUsername($username)
{
if($user->getAuthType() == User::LOGIN_LDAP) {
$this->properProvider = $this->ldapUserProvider;
} elseif($user->getAuthType() == User::LOGIN_NATIVE) {
$this->properProvider = $this->fosUserProvider;
} else {
throw new InvalidArgumentException('Error');
}
}
public function loadUserByUsername($username)
{
return $this->chooseProviderForUsername($username)->loadUserByUsername($username);
}
问题:链提供商不是一个选项 - 它允许用户使用他的LDAP密码和本地密码登录!这是一个很大的安全问题。
是否有办法通过不同的身份验证提供程序登录用户,具体取决于db字段?
编辑:
我的security.yml:
providers:
fos_userbundle:
id: fos_user.user_provider.username
appbundle_user_provider:
id: appbundle.user_provider
fr3d_ldapbundle:
id: fr3d_ldap.security.user.provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
pattern: ^/admin.*
context: user
fr3d_ldap: ~
form_login:
provider: appbundle_user_provider
csrf_provider: security.csrf.token_manager
always_use_default_target_path: true
default_target_path: admin_main
login_path: /admin/login
check_path: /admin/login_check
logout:
path: /admin/logout
target: /admin/login
anonymous: true
这是security.yml。此行fr3d_ldap: ~
启用ldap捆绑包,该捆绑包授权ldap用户并将其保存到我的数据库中。没有它我无法授权它们,可能我必须编写自定义AuthenticationProvider。
答案 0 :(得分:1)
我对ldap不是很熟悉,但我建议尝试完全手动登录
$token = new UsernamePasswordToken($user, null, "firewallname", $user->getRoles());
$securityContext = $this->container->get('security.context');
$securityContext->setToken($token);
然后您可以自己手动执行检查,并根据检查结果决定在进行身份验证之前如何验证用户。例如,在执行此登录代码之前,请按用户名和密码运行查询,具体取决于您想要的db字段。
答案 1 :(得分:0)
您的方法似乎很好,但您应该检查您的方法的逻辑。 首先是这一个:
public function chooseProviderForUsername($username)
{
if($user->getAuthType() == User::LOGIN_LDAP) {
$this->properProvider = $this->ldapUserProvider;
} elseif($user->getAuthType() == User::LOGIN_NATIVE) {
$this->properProvider = $this->fosUserProvider;
} else {
throw new InvalidArgumentException('Error');
}
}
您将$username
作为参数传递给此方法,但随后使用$user
对象,这在当前上下文中似乎未定义。
其次:
public function loadUserByUsername($username)
{
return $this->chooseProviderForUsername($username)->loadUserByUsername($username);
}
因为chooseProviderForUsername
方法实际上没有返回任何值,所以你无法以这种方式链接它。
我希望重构这些问题可以使您的提供商正常工作。
答案 2 :(得分:0)
好的,非常简短的回答,但我认为目前Symfony正在搜索任何旧用户提供商中的用户而不是那个特定用户想要的用户(这解释了整个用两个密码登录的东西)。解决方案应该是AppBundleUserProvider
实施UserProviderInterface
,从security.yml
删除其他用户提供商,然后确保AppBundleUserProvider
做的第一件事就是找出哪个用户提供商对于该用户是必需的,然后模仿UserProviderInterface
中的每个方法。您可以根据用户名设置$this->realUP
,然后将每个方法设置为仅返回$this->realUP->someMethod()
。
答案 3 :(得分:0)
我能想到的最简洁的方法是创建自己的ChainProvider class,只允许使用一个提供商和use the Dependency Injection Container to use yours登录。
您只需要覆盖捆绑包配置文件中的 security.user.provider.chain.clas 参数定义。