现有代码中有 2 个主要问题:
- Symfony 的
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'
);
};
注意第三个和第四个参数可以是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'
);
});
}
}