В последнее время я всерьёз заморочился темой построения сервисов по принципу "Single Sign-On". По понятным причинам, применительно к связке "Windows-клиент + AD + LAMP" я рассматриваю только Kerberos + GSSAPI/SPNEGO. По мере погружения в вопрос выяснилась одна неприятная особенность: под это дело приходится переделывать и веб-приложение в том числе.
Взять и ввести в виндовый домен линуксовую машинку относительно несложно. Сделать так, чтобы она кушала бы Krb-мандаты, передаваемые клиентом, тоже можно. Но дальше всплывает принципиальный затык.
Для того, чтобы браузер отослал свой мандат серверу, последний должен сперва явно его затребовать заголовками "401 Authorization Required" и "WWW-Authenticate". Другими словами, для данного ресурса должна быть жестко задана аутентификация на уровне веб-сервера (а не на уровне приложения).
Но если мы включаем аутентификацию на уровне сервера, то не имеющие валидных krb-мандатов пользователи сразу же отсекаются и до приложения просто не доходят. То есть шанса ввести логин-пароль у них в общем случае¹ уже нет.
Отсюда следует вывод, что для корректного срабатывания необходимо перестраивать логику работы самого приложения. А именно, разделять его на две части: сервис отдельно, скрипты аутентификации отдельно. То есть, допустим, при запуске какого-либо скрипта из сервисной части, оный сперва проверяет наличие у пользователя некой печеньки (cookie). Если таковая обнаруживается, то аутентифицируем клиента по печеньке и работаем себе дальше безо всякого Kerberos. Если же нет, то редиректим клиента на отдельный скрипт аутентификации, находящейся в той области (Location) веб-сервера, которая в обязательном порядке требует krb-мандат.
Далее два варианта.
- Kerberos отрабатывает, скрипт получает от сервера $_SERVER['REMOTE_USER'] (в синтаксисе PHP5), выдает пользователю соответствующую печеньку (cookie), редиректит обратно на ту же страницу, откуда клиент к нему пришел (Referrer).
- Kerberos обваливается с ошибкой, но на этот случай у нас припасена заранее заготовленная HTML-страничка а-ля "ErrorDocument 401", внутри которой в числе прочего содержится
<meta http-equiv="refresh" content="0;url=loginpage.html">
Браузер кушает эту страничку и идёт по указанному в ней адресу на форму логина, которая, по задумке, на уровне сервера открыта для всех.
Как видно, всё это работать будет (я лично тестировал), но вот конкретное приложение под это дело придётся достаточно существенно "перепиливать". То есть, например, ту же самую Dokuwiki, просто вот так вот, с пол-пинка под это дело заточить не удастся, несмотря даже на то, что к ней в комплекте изначально уже прилагается соответствующий плагин. Сиё есть пичалька.
----------
¹ На самом деле для большинства популярных веб-серверов kerberos-плагины умеют в случае отлупа по SPNEGO запросить у пользователя логин-пароль в Plain Text. Но это убогое окно в стиле Basic Auth с полным отсутствием наглядной сопроводительной информации я в качестве решения вопроса всерьёз не рассматриваю.