我正在尝试让LDAP身份验证适用于Symfony防火墙,但遇到了麻烦。主要问题似乎来自Symfony LdapUserProvider
- 在尝试ldap_bind()
时,用户不会提供用户名和密码。
所以,我把它作为我的防火墙配置:
$app->register(new SilexProvider\SecurityServiceProvider(), [
'security.firewalls' => [
'secured' => [
'pattern' => '^.*$',
'http' => true,
'users' => new \Symfony\Component\Security\Core\User\LdapUserProvider(
\Symfony\Component\Ldap\Ldap::create('ext_ldap', [
'connection_string' => 'ldap://MY_LDAP_DOMAIN',
]),
'dc=MY_DC_1,dc=MY_DC_2',
'uid={username},cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2'
),
],
],
]);
但是,在调用{username}
方法时,我的ldap_bind
部分不会被用户提供的用户名替换。因此,传递给dn
的{{1}}字符串实际上是ldap_bind
- 用户名不会被替换。
如果我仔细查看代码,那么uid={username},cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2
会在执行任何字符串替换之前调用LdapUserProvider->loadUserByUsername()
。另一个问题是它在很久之后才知道用户提供的密码,因此再次bind
调用没有用户提供的密码。
如何设置它以便它会适当地替换我的bind
和密码?如果我使用这两条基本行(其中dn
是有效用户的数组):
$data
然后它完美结合。如何将这两行转换为Symfony防火墙理解的情况?
答案 0 :(得分:3)
现有代码中存在 2 主要问题:
LdapUserProvider
组件默认使用Active Directory(Windows)架构:sAMAccountName={username}
而不是Open LDAP' uid={username}
http
安全防火墙,默认情况下使用DaoAuthenticationProvider
身份验证提供程序。如果是LDAP身份验证,则需要使用LdapBindAuthenticationProvider
代替。 第一个问题可以通过将用户标识符密钥传递给LdapUserProvider
来解决:
$app['ldap.users'] = function () use ($app) {
return new LdapUserProvider(
// your LDAP adapter
$app['ldap'],
// base DN
'dc=example,dc=com',
// you don't need search DN
null,
// you don't need search password
null,
// list of default roles, can be empty array
['ROLE_USER'],
// user identifier key for LDAP
// this identitfer must be set explicitly
'uid'
);
};
注意第3和第4个参数可以是null
,因为它们永远不会被使用:LdapBindAuthenticationProvider
将首先被调用,因此LDAP连接已被绑定。
第二个问题需要一点点编码。 Symfony具有内置的http_basic_ldap
身份验证提供程序,完全符合您的要求。不幸的是,Silex没有,所以你需要自己做。使用Silex文档作为参考:Defining a custom Authentication Provider
以下是我为Silex实施form_login_ldap
的示例。
注册所有与LDAP相关的服务:
$app // register other services
->register(new LdapServiceProvider())
->register(new LdapUsersServiceProvider())
->register(new LdapSecurityServiceProvider())
->register(new \Silex\Provider\SecurityServiceProvider(), [
'security.firewalls' => [
'login' => [
'pattern' => '^/login$',
],
'secured' => [
'pattern' => '^.*$',
'form_login_ldap' => [
'login_path' => 'login',
'check_path' => 'login_check',
'default_target_path' => 'backoffice',
],
'users' => $this['ldap.users'],
],
],
])
;
LDAP适配器的服务提供商
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Ldap\Ldap;
class LdapServiceProvider implements ServiceProviderInterface
{
public function register(Container $app)
{
$app['ldap'] = function () {
return Ldap::create('ext_ldap', [
'connection_string' => 'ldap.example.com',
]);
};
}
}
LDAP用户的服务提供商
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Security\Core\User\LdapUserProvider;
class LdapUsersServiceProvider implements ServiceProviderInterface
{
public function register(Container $app)
{
$app['ldap.users'] = function () use ($app) {
return new LdapUserProvider(
$app['ldap'],
'dc=example,dc=com',
null,
null,
['ROLE_USER'],
'uid'
);
};
}
}
LDAP表单安全验证侦听器工厂的服务提供商(最有趣的部分)
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Security\Core\Authentication\Provider\LdapBindAuthenticationProvider;
class LdapSecurityServiceProvider implements ServiceProviderInterface
{
public function register(Container $app)
{
$app['security.authentication_listener.factory.form_login_ldap'] = $app->protect(function ($name, $options) use ($app) {
// define the authentication provider object
$app['security.authentication_provider.'.$name.'.form_login_ldap'] = function () use ($app, $name) {
return new LdapBindAuthenticationProvider(
$app['security.user_provider.'.$name],
$app['security.user_checker'],
$name,
$app['ldap'],
'uid={username},dc=example,dc=com',
$app['security.hide_user_not_found']
);
};
// define the authentication listener object
$app['security.authentication_listener.'.$name.'.form_login_ldap'] = $app['security.authentication_listener.form._proto']($name, $options);
// define the entry point object
$app[$entryPoint = 'security.entry_point.'.$name.'.form_login_ldap'] = $app['security.entry_point.form._proto']($name, array());
return array(
// the authentication provider id
'security.authentication_provider.'.$name.'.form_login_ldap',
// the authentication listener id
'security.authentication_listener.'.$name.'.form_login_ldap',
// the entry point id
$entryPoint,
// the position of the listener in the stack
'form'
);
});
}
}