NTLM-аутентификация на Symfony 2

На самом деле я создаю интрасеть с Symfony 2, и мне нужно автоматически регистрировать пользователей (я имею в виду отсутствие формы входа...). На данный момент я использую метод из моего контроллера, который меняет заголовки для запуска аутентификации NTLM на браузер. Это работает хорошо, но после того, как пользователь вошел в систему, он не может отправить какую-либо форму POST: все значения пусты. Все эти проблемы есть в Internet Explorer, в Firefox и Chrome все в порядке. Для использования этого метода мне пришлось включить KeepAlive в моей конфигурации Apache, чтобы он работал в Internet Explorer.

Я использую этот код для входа пользователя через NTLM:

public function getInfos() {

    $headers = apache_request_headers();
    $infos = array();

    if (!isset($headers['Authorization'])) {
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: NTLM');
        exit;
    }

    $auth = $headers['Authorization'];

    if (substr($auth, 0, 5) == 'NTLM ') {
        $msg = base64_decode(substr($auth, 5));
        if (substr($msg, 0, 8) != "NTLMSSP\x00")
            die('error header not recognised');

        if ($msg[8] == "\x01") {
            $msg2 = "NTLMSSP\x00\x02\x00\x00\x00" .
                    "\x00\x00\x00\x00" . // target name len/alloc
                    "\x00\x00\x00\x00" . // target name offset
                    "\x01\x02\x81\x00" . // flags
                    "\x00\x00\x00\x00\x00\x00\x00\x00" . // challenge
                    "\x00\x00\x00\x00\x00\x00\x00\x00" . // context
                    "\x00\x00\x00\x00\x00\x00\x00\x00"; // target info len/alloc/offset

            header('HTTP/1.1 401 Unauthorized');
            header('WWW-Authenticate: NTLM ' . trim(base64_encode($msg2)));
            exit;
        } else if ($msg[8] == "\x03") {

            function get_msg_str($msg, $start, $unicode = true) {
                $len = (ord($msg[$start + 1]) * 256) + ord($msg[$start]);
                $off = (ord($msg[$start + 5]) * 256) + ord($msg[$start + 4]);
                if ($unicode)
                    return str_replace("\0", '', substr($msg, $off, $len));
                else
                    return substr($msg, $off, $len);
            }

            $user = get_msg_str($msg, 36);
            $domain = get_msg_str($msg, 28);
            $workstation = get_msg_str($msg, 44);

            $infos = array('login' => $user, 'domaine' => $domain, 'machine' => $workstation);
        }
    }
    return $infos;
}

Я искал другой способ, но для тех, кто работает с Symfony: проблемы слишком старые, поэтому, если у вас есть идея, как решить эту проблему или другой лучший и более чистый способ сделать это с Symfony.


person Joffrey Carle    schedule 25.06.2013    source источник
comment
Вы хотите, чтобы базовое всплывающее окно HTTP-аутентификации? что вы подразумеваете под автоматическим входом пользователя? Для аутентификации пользователь должен сказать, кто он/она? В безопасности symfony есть много механизмов аутентификации (базовый http, вход через форму и т.д.).   -  person vishal    schedule 11.04.2014


Ответы (2)


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

То, что IE относится к аутентификации NTLM и пустому POST, - это функция (!), позволяющая избежать ненужной нагрузки на сеть:

Когда какому-то элементу на странице требуется рукопожатие NTLM, IE предполагает, что для всех будущих запросов (в области домена) потребуется аутентификация NTLM... Чтобы сохранить сеть, IE будет отправлять только содержимое POST в третьем раунде ожидаемого рукопожатия. . Если ваше приложение не запускает эту аутентификацию, содержимое POST никогда не отправляется.

Это подробно объясняется (и более словами, чем мои) здесь: http://blogs.msdn.com/b/ieinternals/archive/2010/11/22/internet-explorer-post-bodies-являютсянулевымибайтамивдлине,когда-вызовы-аутентификации-ожидаются.aspx.

Чтобы решить вашу проблему, вам нужно реализовать аутентификацию NTLM для каждого вызова (или каждого последующего вызова после запуска первого), вы можете сделать это с помощью пользовательских брандмауэров / поставщиков аутентификации, как указано в онлайн-документе Symfony2: http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html.

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

person Nicolas Binand    schedule 05.10.2015
comment
Что ж, спасибо, я некоторое время искал такой ответ, но, наконец, я сделал это по-другому: - Понизить версию фреймворка, чтобы она соответствовала версии, необходимой для пакета, рекомендованного @Paul Andrieux. - Использовать этот пакет для аутентификации NTLM. :) - person Joffrey Carle; 07.10.2015

Этот пакет делает то, что вы хотите? https://github.com/ecoad/NtlmBundle

Он совместим с sf2.0, поэтому вам, возможно, придется обновить его до последней версии sf.

person Paul Andrieux    schedule 14.04.2014
comment
Хорошо. Спасибо, так как я понизил версию своей платформы и адаптировал ее для своей проблемы. - person Joffrey Carle; 07.10.2014