Symfony LDAP auth связывается с именем пользователя и паролем

Я пытаюсь получить аутентификацию LDAP для брандмауэра Symfony, но у меня проблемы. Основная проблема, по-видимому, связана с Symfony LdapUserProvider – при попытке ldap_bind() пользователь не 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 метод ldap_bind . Таким образом, строка dn переданная в ldap_bind является буквально uid={username},cn=users,cn=accounts,dc=MY_DC_1,dc=MY_DC_2 – имя пользователя не заменяется.

Если я просмотрю код, хотя это ожидается, так как LdapUserProvider->loadUserByUsername() вызывает bind перед выполнением любых заменой строк. Другая проблема заключается в том, что он не знает пароль, предоставленный пользователем, до тех пор, пока он не будет намного позже, поэтому вызов пересылки еще не имеет пароля, предоставленного пользователем.

Как я могу настроить это так, чтобы он надлежащим образом заменил мои dn и пароль? Если я использую эти 2 основные строки (где $data – массив действительного пользователя):

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

Тогда он прекрасно связывается. Как я могу перевести эти 2 строки в ситуацию, которую понимает брандмауэр Symfony?

У вас есть 2 основных вопроса в существующем коде:

  1. Компонент LdapUserProvider от Symfony по умолчанию использует схему Active Directory (Windows): sAMAccountName={username} вместо Open LDAP uid={username}
  2. Вы используете встроенный http брандмауэр, который по умолчанию использует DaoAuthenticationProvider аутентификации 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 будет вызван LdapBindAuthenticationProvider , поэтому соединение LDAP уже будет связано.

Вторая проблема требует немного кодирования. У Symfony есть встроенный http_basic_ldap аутентификации http_basic_ldap который идеально подходит вашим требованиям. К сожалению, у Silex его нет, поэтому вам нужно сделать это самостоятельно. Использовать документацию Silex для справки: определение пользовательского поставщика проверки подлинности

Вот мой пример реализации form_login_ldap для Silex. Регистрация всех связанных с 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' ); }); } }