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

Дата обновления перевода 2022-02-03

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

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

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

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

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

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

Установка

В приложениях, использующих Symfony Flex, выполните эту команду, чтобы установить компонент Ldap, перед его использованием:

1
$ composer require symfony/ldap

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

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

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

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

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

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/services.yaml
services:
    Symfony\Component\Ldap\Ldap:
        arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
        tags:
            - ldap
    Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
        arguments:
            -   host: my-server
                port: 389
                encryption: tls
                options:
                    protocol_version: 3
                    referrals: false

Извлечение пользователей, используя поставщика пользователей LDAP

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

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/packages/security.yaml
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
                extra_fields: ['email']

Caution

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

Caution

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

Если ваш LDAP-сервер позволяет анонимное извлечение информации, вы можете установить опции search_dn м search_password как null.

Поставщик пользователей 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

Если вы передадите null как значение этой оцпии, используется ключ UID по умолчанию - sAMAccountName.

extra_fields

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

Определяет пользовательские поля для пуллинга со LDAP-сервера. Если какое-то поле не существует, будет вызвано \InvalidArgumentException.

filter

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

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

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

Если вы передадите null как значение этой опции, используется фильтр по умолчанию - ({uid_key}={username}).

Чтобы предотвратить внедрение 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}"). Значение заполнителя будет заменено настоящим именем пользователя.

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

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

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

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

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
# config/packages/security.yaml
security:
    # ...

    firewalls:
        main:
            # ...
            form_login_ldap:
                # ...
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'uid={username},dc=example,dc=com'

Configuration example for HTTP Basic

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
# config/packages/security.yaml
security:
    # ...

    firewalls:
        main:
            stateless: true
            http_basic_ldap:
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'uid={username},dc=example,dc=com'

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

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
# config/packages/security.yaml
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))'
                search_dn: '...'
                search_password: 'the-raw-password'