Symfony LDAP auth bind with username and password

浪子不回头ぞ 提交于 2019-12-07 15:05:24

You have 2 main issues in the existing code:

  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.

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

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.

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

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

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

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

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'
            );
        });
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!