2

我实际上正在使用 Symfony 2 构建一个内部网,并且我必须自动登录用户(我的意思是没有登录表单......).. 目前,我正在使用我的控制器中的一种方法来更改标题以启动 NTLM 身份验证浏览器。它运行良好,但用户登录后,他无法发送任何 POST 表单:所有值都是空的。所有这些问题都在 Internet Explorer、Firefox 和 Chrome 上,没关系。为了使用这种方法,我必须在我的 Apache 配置中将 KeepAlive 设置为 On 以使其在 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 解决这个问题的另一种更好更干净的方法。

4

2 回答 2

2

很抱歉回答这个老问题,但是当我面临同样的问题时,我正在为未来的小伙子分享一些线索:

关于 NTLM 身份验证和空 POST 的 IE 是一个功能(!),以避免网络不必要的负载:

当页面上的某些元素需要 NTLM 握手时,IE 假定所有未来的请求(在域范围内)都需要 NTLM 身份验证...为了保护网络,IE 将在第三轮预期握手时仅发送 POST 内容. 如果您的应用未触发此身份验证,则永远不会发送 POST 内容。

这在此处进行了详细解释(并且用比我更好的词):http: //blogs.msdn.com/b/ieinternals/archive/2010/11/22/internet-explorer-post-bodies-are-zero-bytes -in-length-when-authentication-challenges-are-expected.aspx

为了解决您的问题,您需要在每个调用(或触发第一个调用后的每个后续调用)上实现 NTLM 身份验证,您可以使用 Symfony2 在线文档中起草的海关防火墙/身份验证提供程序来执行此操作:http:/ /symfony.com/doc/current/cookbook/security/custom_authentication_provider.html

由于这并不容易实现,因此我建议您使用现有的 Bundle 来更多地关注您的代码,而不是这些痛苦的功能。

于 2015-10-05T12:51:51.667 回答
1

这个捆绑包做你想要的吗? https://github.com/ecoad/NtlmBundle

它是 sf2.0 兼容的,所以你可能需要为最近的 sf 版本更新它。

于 2014-04-14T10:03:50.790 回答