← Back to blog
Blog

Active Directory + PHP: единая авторизация для корпоративных приложений

Зачем нужна единая авторизация?

В корпоративной среде десятки сервисов: почта, CRM, ERP, внутренние порталы. Если у каждого свой логин и пароль — пользователи забывают, администраторы тонут в запросах на сброс. Решение — единая точка входа через Active Directory.

Подключаем LDAP в PHP

Для работы с AD используем расширение ldap. Устанавливаем, если нет:

sudo apt install php8.2-ldap

Подключаемся к серверу:

$ldap = ldap_connect('ldap://dc.company.local', 389);
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

// Аутентификация
$bind = ldap_bind($ldap, 'CN=php_service,OU=Service Accounts,DC=company,DC=local', $password);

Ищем пользователя

Поиск по sAMAccountName (логин Windows):

$filter = '(sAMAccountName=' . ldap_escape($username) . ')';
$result = ldap_search($ldap, 'DC=company,DC=local', $filter);
$entries = ldap_get_entries($ldap, $result);

if ($entries['count'] > 0) {
    $user = $entries[0];
    echo $user['displayname'][0];  // Иванов Иван
    echo $user['mail'][0];         // ivanov@company.local
    echo $user['memberof'];        // Группы
}

Синхронизация пользователей

Раз в ночь выгружаем всех активных пользователей из AD в локальную БД:

$filter = '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';
$result = ldap_search($ldap, 'OU=Users,DC=company,DC=local', $filter);
$entries = ldap_get_entries($ldap, $result);

for ($i = 0; $i < $entries['count']; $i++) {
    User::updateOrCreate(
        ['ad_login' => $entries[$i]['samaccountname'][0]],
        [
            'name'  => $entries[$i]['displayname'][0] ?? '',
            'email' => $entries[$i]['mail'][0] ?? '',
            'department' => $entries[$i]['department'][0] ?? '',
        ]
    );
}

Роли и разрешения

AD-группы маппим на локальные роли. Создаём таблицу ad_group_role:

Schema::create('ad_group_role', function (Blueprint $table) {
    $table->string('ad_group');       // CN=Accounting,OU=Groups,DC=company,DC=local
    $table->string('local_role');     // accountant
});

При логине проверяем memberof и выдаём соответствующие роли:

$groups = $user['memberof'] ?? [];
foreach ($groups as $group) {
    $role = AdGroupRole::where('ad_group', $group)->first();
    if ($role) {
        $localUser->assignRole($role->local_role);
    }
}

Интеграция с другими сервисами

Единая авторизация позволяет без паролей подключать:

  • Внутренние порталы и вики
  • Системы документооборота
  • Корпоративный чат
  • CI/CD и мониторинг

Всё через один логин и пароль пользователя Windows.

Итог

Active Directory + LDAP — стандарт корпоративной авторизации. Интеграция с PHP занимает 1-2 дня, а экономит месяцы поддержки отдельных учёток. Пользователи благодарят, администраторы отдыхают.