Symfony LDAP 身份验证绑定用户名和密码 [英] Symfony LDAP auth bind with username and password

查看:43
本文介绍了Symfony LDAP 身份验证绑定用户名和密码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让 LDAP 身份验证适用于 Symfony 防火墙,但遇到了问题.主要问题似乎源于 Symfony LdapUserProvider - 在尝试 ldap_bind() 时它不需要用户提供的用户名和密码.

I am trying to get LDAP authentication working for Symfony firewall but am having trouble. The main issue seems to stem from the Symfony LdapUserProvider - it does not take the user supplied username and password when trying ldap_bind().

所以,我把它作为我的防火墙配置:

So, I have this as my firewall config:

$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'
            ),
        ],
    ],
]);

但是当调用 ldap_bind 方法时,我的 {username} 部分不会被用户提供的用户名替换.因此,传递给 ldap_binddn 字符串实际上是 uid={username},cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2 - 用户名不会被替换.

But my {username} part is not replaced by the user supplied username when the ldap_bind method is called. So, the dn string passed to ldap_bind is literally uid={username},cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2 - the username isn't replaced.

如果我查看代码虽然这是预期的,因为 LdapUserProvider->loadUserByUsername() 在执行任何字符串替换之前调用 bind.另一个问题是它直到很久以后才知道用户提供的密码,因此 bind 再次调用没有用户提供的密码.

If I look through the code though this is expected, as LdapUserProvider->loadUserByUsername() calls bind before doing any string replacements. The other problem is that it does not know the user supplied password until much later, so the bind call again doesn't have the user supplied password.

如何设置它以适当地替换我的 dn 和密码?如果我使用这两条基本行(其中 $data 是有效用户的数组):

How can I set this up so that it will replace my dn and password appropriately? If I use these 2 basic lines (where $data is an array of a valid user):

$ldap = ldap_connect('MY_LDAP_DOMAIN');
$bind = ldap_bind($ldap, 'uid=' . $data['username'] . ',cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2', $data['password']);

然后它完美结合.我如何将这两行转换为 Symfony 防火墙理解的情况?

Then it binds perfectly. How can I translate those 2 lines into a situation that Symfony firewall understands?

推荐答案

您在现有代码中存在 2 个主要问题:

You have 2 main issues in the existing code:

  1. Symfony 的 LdapUserProvider 组件默认使用 Active Directory (Windows) 架构:sAMAccountName={username} 而不是 Open LDAP 的 uid={username}>
  2. 您正在使用内置的 http 安全防火墙,默认情况下使用 DaoAuthenticationProvider 身份验证提供程序.如果是 LDAP 身份验证,则需要使用 LdapBindAuthenticationProvider 代替.
  1. Symfony's LdapUserProvider component by default uses Active Directory (Windows) schema: sAMAccountName={username} instead of Open LDAP's uid={username}
  2. You're using built-in http security firewall, which by default uses DaoAuthenticationProvider authentication provider . In case of LDAP authentication, you need to use LdapBindAuthenticationProvider instead.

第一个问题可以通过将用户标识符密钥传递给LdapUserProvider来解决:

The first issue can be solved by passing user identifier key to 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连接已经被绑定.

Notice 3rd and 4th parameters can be null, because they will never be used: LdapBindAuthenticationProvider will be invoked first, so LDAP connection already will be bound.

第二个问题需要一些编码.Symfony 具有内置的 http_basic_ldap 身份验证提供程序,非常适合您的要求.不幸的是,Silex 没有,所以你需要自己做.使用 Silex 文档作为参考:定义一个自定义身份验证提供程序

The second issue requires a little bit of coding. Symfony has built-in http_basic_ldap authentication provider which perfectly suits your requirements. Unfortunately, Silex doesn't have one, so you need to do it on your own. Use Silex documentation for reference: Defining a custom Authentication Provider

这是我的 Silex form_login_ldap 实现示例.注册所有与 LDAP 相关的服务:

Here is my example of form_login_ldap implementation for Silex. Registering all LDAP-related services:

$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 适配器的服务提供商

Service Provider for LDAP Adapter

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 用户的服务提供商

Service Provider for LDAP Users

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 表单的安全认证侦听器工厂的服务提供者(对您来说最有趣的部分)

Service Provider for Security Authentication Listener Factory for LDAP Form (the most interesting part for you)

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'
            );
        });
    }
}

这篇关于Symfony LDAP 身份验证绑定用户名和密码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆