Аутентификация с LDAP-сервером

Symfony предоставляет разные способы работы с LDAP-сервером.

Компонент Безопасность предлагает:

  • Поставщика пользователя ldap, использующего класс LdapUserProvider. Как и все другие поставщики пользователей, он может быть использован с любым поставщиком аутентификации.
  • Поставщик аутентификации form_login_ldap, для аутентификации с LDAP-сервером, используя форму входа. Как и все другие поставщики аутентификации, может быть использован с любым поставщиком пользователя.
  • Поставщик аутентификации http_basic_ldap, для аутентификации с LDAP-сервером, используя Базовый HTTP. Как и все другие поставщики аутентификации, может быть использован с любым поставщиком пользователя.

Это означает, что следующие сценарии будут работать:

  • Проверка пароля пользователя и выборка информации пользователя с LDAP-сервером. Это может быть сделано с использованием как поставщика пользователя LDAP, так и с формой входа LDAP или поставщиками аутентификации LDAP базового HTTP.
  • Проверка пароля пользователя с LDAP-сервером во время выборки информации из другого источника (БД, использующей FOSUserBundle, например).
  • Загрузка информации пользователя с LDAP-сервера вовремя использования другой стратегии аутентификации (например, предварительной аутентификации на основании токена).

Справочник Ldap-конфигурации

Смотрите SecurityBundle Configuration ("security"), чтобы увидеть полный справочник LDAP-конфигурации (form_login_ldap, http_basic_ldap, ldap). Некоторые наиболее интересные опции разъясняются ниже.

Конфигурация LDAP-клиента

Все механизмы на самом деле нуждаются в предварительно сконфигурированном LDAP-клиенте. Поставщики конфигурируются так, чтобы по умолчанию использовать сервис под названием ldap, но вы можете переопределить эту настройку в конфигурации компонента безопасности.

LDAP-клиент может быть просто сконфигурирован, используя встроенное PHP-расширение LDAP со следующим определением сервиса:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    # app/config/services.yml
    services:
        Symfony\Component\Ldap\Ldap:
            arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
        Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
            arguments:
                -   host: my-server
                    port: 389
                    encryption: tls
                    options:
                        protocol_version: 3
                        referrals: false
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!-- app/config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="Symfony\Component\Ldap\Ldap">
                <argument type="service" id="Symfony\Component\Ldap\Adapter\ExtLdap\Adapter" />
            </service>
            <service id="Symfony\Component\Ldap\Adapter\ExtLdap\Adapter">
                <argument type="collection">
                    <argument key="host">my-server</argument>
                    <argument key="port">389</argument>
                    <argument key="encryption">tls</argument>
                    <argument key="options" type="collection">
                        <argument key="protocol_version">3</argument>
                        <argument key="referrals">false</argument>
                    </argument>
                </argument>
            </service>
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // app/config/services.php
    use Symfony\Component\Ldap\Ldap;
    use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
    use Symfony\Component\DependencyInjection\Definition;
    
    $container->register(Ldap::class)
        ->addArgument(new Reference(Adapter::class);
    
    $container
        ->register(Adapter::class)
        ->setArguments(array(
            'host' => 'my-server',
            'port' => 389,
            'encryption' => 'tls',
            'options' => array(
                'protocol_version' => 3,
                'referrals' => false
            ),
        ));
    

Выборка пользователей с использованием поставщика пользователя LDAP

Если вы хотите извлечь информацию пользователя с LDAP-сервера, вы можете захотеть использовать поставщика пользователя ldap.

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # app/config/security.yml
    security:
        # ...
    
        providers:
            my_ldap:
                ldap:
                    service: Symfony\Component\Ldap\Ldap
                    base_dn: dc=example,dc=com
                    search_dn: "cn=read-only-admin,dc=example,dc=com"
                    search_password: password
                    default_roles: ROLE_USER
                    uid_key: uid
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!-- app/config/security.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <config>
            <provider name="my_ldap">
                <ldap
                        service="Symfony\Component\Ldap\Ldap"
                        base-dn="dc=example,dc=com"
                        search-dn="cn=read-only-admin,dc=example,dc=com"
                        search-password="password"
                        default-roles="ROLE_USER"
                        uid-key="uid"
                />
            </provider>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    use Symfony\Component\Ldap\Ldap;
    
    $container->loadFromExtension('security', array(
        'providers' => array(
            'ldap_users' => array(
                'ldap' => array(
                    'service' => Ldap::class,
                    'base_dn' => 'dc=example,dc=com',
                    'search_dn' => 'cn=read-only-admin,dc=example,dc=com',
                    'search_password' => 'password',
                    'default_roles' => 'ROLE_USER',
                    'uid_key' => 'uid',
                ),
            ),
        ),
    );
    

Caution

Компонент Безопасность экранирует предоставленные данные ввода, когда используется LDAP-пользователь. Однако, компонент LDAP сам по себе пока не предоставляет никакого экранрования. Поэтому, ваша задача - предотвратить внедрение LDAP-атак при использовании компонента напрямую.

Поставщик пользователя ldap поддерживает много различных опций конфигурации:

service

тип: string по умолчанию: ldap

Это имя вашего сконфигурированного LDAP-клиента. Вы можете свободно выбирать имя, но оно должно быть уникальным в вашемприложении и не может начинаться с цифры или содержать пробелы.

base_dn

тип: string по умолчанию: null

Это базовое отличительное имя для каталога.

search_dn

тип: string по умолчанию: null

Это отличительное имя вашего пользователя, доступное только для чтения, которое будет использовано для аутентификации с LDAP-сервером, чтобы извлечь информацию пользователя.

search_password

тип: string по умолчанию: null

Это пароль вашего пользователя, доступный только для чтения, который будет аутентифицирован с LDAP-сервером для того, чтобы извлечь информацию пользователя.

default_roles

тип: array по умолчанию: []

Это роль по умолчанию, которую вы хотите дать пользователю, извлечённому с LDAP-сервера. Если вы не сконфигурируете этот включ, ваши пользователи не будут иметь никаких ролей ине будут приняты, как полностью аутентифицированные.

uid_key

тип: string по умолчанию: sAMAccountName

Это ключ входа для использования в качестве идентификатора пользователя. Зависит от реализации вашего LDAP-сервера. Наиболее часто используемыми значениями являются:

  • sAMAccountName
  • userPrincipalName
  • uid

filter

тип: string по умолчанию: ({uid_key}={username})

Этот ключ позволяет вам сконфигурировать, какой LDAP-запрос будет использован. Строка {uid_key} будет заменена значением конфигурации uid_key``(по умолчанию, ``sAMAccountName), а строка {username} будет заменена именем пользователя, которого вы пытаетесь загрузить.

Например, с uid_key в uid, и если вы пытаетесь загрузить пользователя fabpot, финальной строкой будет (uid=fabpot).

Конечно же, имя пользователя будет экранировано, чтобы предотвратить внедрение LDAP.

Синтаксис для ключа filter определяется RFC4515.

Аутентификация с LDAP-сервером

Аутентификация с LDAP-сервром может быть проведена с использованием либо формы входа или базовых поставщиков аутентификации HTTP.

Они конфигурируются точно так же, как их копии, не имеющие отношения к LDAP, с добавлением двух ключей конфигурации и одного необязательного ключа:

service

тип: string по умолчанию: ldap

Это имя вашего сконфигурированного LDAP-клиента. Вы можете свободно выбирать имя, но оно должно быть уникальным в вашемприложении и не может начинаться с цифры или содержать пробелы.

dn_string

тип: string по умолчанию: {username}

Этот ключ определяет форму строки, использованной для составления отличительного имени пользователя из имени пользователя. Строка {username} заменяется настоящим именем пользователя человека, который проходит аутентификацию.

Например, если ваши пользователи имеют строки отличительного имени в виде uid=einstein,dc=example,dc=com, то dn_string будет uid={username},dc=example,dc=com.

query_string

тип: string по умолчанию: null

Этот (необязательый) ключ заставляет вашего поставщика пользоваеля искать пользователя а потом использовать найденное отличительное имя для процесса связывания. Это полезно при использовании нескольких поставщиков пользователей LDAP с разными base_dn. Значение этой опции должно быть валидной строкой поиска (например, uid="{username}"). Значение заполнителя будет заменено настоящим именем пользователя.

Когда используется эта опция, dn_string должен быть соответствующе обновлён. Следуя предыдущему примеру, если ваши пользователи имеют два таких отличительных имени: dc=companyA,dc=example,dc=com и dc=companyB,dc=example,dc=com, то dn_string должен быть dc=example,dc=com. Если опция query_string - uid="{username}", то поставщик аутентификации может аутентифицировать пользователей из обоих отличительных имён.

Помните, что имена пользователей должны быть уникальными в обоих отличительных именах, так как поставщик аутентификации не сможет выбрать правильного пользователя для процесса связывания, если будет найдено более одного.

Примеры приведены ниже как для form_login_ldap, так и для http_basic_ldap.

Пример конфигурации для формы входа

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # app/config/security.yml
    security:
        # ...
    
        firewalls:
            main:
                # ...
                form_login_ldap:
                    # ...
                    service: Symfony\Component\Ldap\Ldap;
                    dn_string: 'uid={username},dc=example,dc=com'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- app/config/security.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <config>
            <firewall name="main">
                <form-login-ldap
                        service="Symfony\Component\Ldap\Ldap"
                        dn-string="uid={username},dc=example,dc=com" />
            </firewall>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    use Symfony\Component\Ldap\Ldap;
    
    $container->loadFromExtension('security', array(
        'firewalls' => array(
            'main' => array(
                'form_login_ldap' => array(
                    'service' => Ldap::class,
                    'dn_string' => 'uid={username},dc=example,dc=com',
                    // ...
                ),
            ),
        )
    );
    

Пример конфигурации для базового HTTP

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # app/config/security.yml
    security:
        # ...
    
        firewalls:
            main:
                # ...
                http_basic_ldap:
                    # ...
                    service: Symfony\Component\Ldap\Ldap
                    dn_string: 'uid={username},dc=example,dc=com'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- app/config/security.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <config>
            <firewall name="main" stateless="true">
                <http-basic-ldap service="Symfony\Component\Ldap\Ldap" dn-string="uid={username},dc=example,dc=com" />
            </firewall>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    use Symfony\Component\Ldap\Ldap;
    
    $container->loadFromExtension('security', array(
        'firewalls' => array(
            'main' => array(
                'http_basic_ldap' => array(
                    'service' => Ldap::class,
                    'dn_string' => 'uid={username},dc=example,dc=com',
                    // ...
                ),
                'stateless' => true,
            ),
        ),
    );
    

Пример конфигурации для формы входа и query_string

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    # app/config/security.yml
    security:
        # ...
    
        firewalls:
            main:
                # ...
                form_login_ldap:
                    # ...
                    service: Symfony\Component\Ldap\Ldap
                    dn_string: 'dc=example,dc=com'
                    query_string: '(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- app/config/security.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <srv:container xmlns="http://symfony.com/schema/dic/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:srv="http://symfony.com/schema/dic/services"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <config>
            <firewall name="main">
                <form-login-ldap
                        service="Symfony\Component\Ldap\Ldap"
                        dn-string="dc=example,dc=com"
                        query-string="(&amp;(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))" />
            </firewall>
        </config>
    </srv:container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // app/config/security.php
    use Symfony\Component\Ldap\Ldap;
    
    $container->loadFromExtension('security', array(
        'firewalls' => array(
            'main' => array(
                'form_login_ldap' => array(
                    'service' => Ldap::class,
                    'dn_string' => 'dc=example,dc=com',
                    'query_string' => '(&(uid={username})(memberOf=cn=users,ou=Services,dc=example,dc=com))',
                    // ...
                ),
            ),
        )
    );
    

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.