使用 mod_authnz_sspi 在 Apache 2.4 上进行 NTLM 身份验证

NTLM authentication on Apache 2.4 with mod_authnz_sspi

我很难从另一台 Web 服务器访问一台 Apache Web 服务器上的文件。甚至来自同一网络服务器。

首先让我给你介绍一下所涉及的两台服务器的规格。

服务器 1:

Windows Server 2003
Apache 2.2 32bit
PHP 5.2.10

服务器 2:

Windows Server 2012 R2 Standard
Apache 2.4 64bit
PHP 5.6.5

要读取 Windows 远程用户(对于单点登录),我在旧服务器上使用模块 mod_auth_sspi。不幸的是,这个模块在 Apache 2.4 中不再被支持 所以我切换到 mod_authnz_sspi。读取用户名工作正常,但如果我 运行 旧服务器上的 PHP 脚本连接到新服务器并读取那里的文件,脚本得到 使用 HTTP 代码 401(未经授权)拒绝。当我 运行 新服务器上的相同脚本尝试读取旧服务器上的相同文件时,它工作得很好(我希望这个 听起来并不令人困惑。英语也不是我的第一语言,正如你可能已经认识到的那样)。

我使用函数 get_headers() 访问文件,简化后的脚本如下所示:

<?php
    print_r(get_headers("http://server1/test.txt", 1));
    print_r(get_headers("http://server2/test.txt", 1));
?>

test.txt 在两台服务器上都是一个空文件。因此,脚本首先尝试读取一台服务器上的文件,然后是另一台服务器。 结果在两台服务器上看起来是一样的。两者都可以连接到第一台服务器:

[0] => HTTP/1.1 200 OK
[Date] => Mon, 01 Jun 2015 13:18:56 GMT
[Server] => Apache/2.2.11 (Win32) mod_auth_sspi/1.0.4 PHP/5.2.10
[Last-Modified] => Mon, 01 Jun 2015 13:12:58 GMT
[Accept-Ranges] => bytes
[Content-Length] => 0
[Connection] => close
[Content-Type] => text/plain

但是none第二个:

[0] => HTTP/1.1 401 Unauthorized
[Date] => Mon, 01 Jun 2015 13:18:56 GMT
[Server] => Apache/2.4.12 (Win64) mod_authnz_sspi/0.1.0 PHP/5.6.5
[WWW-Authenticate] => Array
    (
        [0] => NTLM
        [1] => Basic realm="mycompany_proxy.loc"
    )
[Content-Length] => 381
[Connection] => close
[Content-Type] => text/html; charset=iso-8859-1

我在Apache access.log 上看了两台服务器。关于test.txt旧的显示没有问题:

[IP address server1] - - [01/Jun/2015:15:22:00 +0200] "GET /test.txt HTTP/1.0" 200 -
[IP address server2] - - [01/Jun/2015:15:18:56 +0200] "GET /test.txt HTTP/1.0" 200 -

另一方面,新的:

[IP address server1] - - [01/Jun/2015:15:22:00 +0200] "GET /test.txt HTTP/1.0" 401 381 "-" "-"
::1 - - [01/Jun/2015:15:18:56 +0200] "GET /test.txt HTTP/1.0" 401 381 "-" "-"

因此旧服务器(server1)和新服务器(通过本地主机)都无法访问该文件。

如果我通过本地计算机上的浏览器从新服务器访问 test.txt(顺便说一句,它工作得很好),可以在日志文件中找到以下条目:

[Local IP address] - - [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 401 381
[Local IP address] - - [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 401 381
[Local IP address] - cdietzel [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 200 -

mod_authnz_sspi 是 httpd.conf 中加载的最后一个模块。对于 htdocs 目录,我尝试了几个首选项,例如这个:

<Directory "c:/Apache24/htdocs">
    Require           all denied
    Order             allow,deny
    Allow             from all
    AllowOverride     All
    Options           None
    AuthName          "mycompany_proxy.loc"
    AuthType          SSPI
    SSPIAuth          On
    SSPIAuthoritative On
    SSPIOfferBasic    On
    SSPIOmitDomain    On
    Require           valid-user
</Directory>

还有这个:

<Directory "c:/Apache24/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
    AuthName "mycompany_proxy.loc"
    AuthType SSPI
    SSPIAuth on
    SSPIAuthoritative on
    SSPIDomain mycompany_proxy.loc
    SSPIOmitDomain on
    SSPIOfferBasic on
    SSPIBasicPreferred on
    SSPIOfferSSPI on
    SSPIMSIE3HACK on    
    require valid-user 
</Directory>

此外,我添加了函数 apache_request_headers(),它在两台服务器上的输出如下所示:

[Host] => server1
[Connection] => keep-alive
[Cache-Control] => max-age=0
[Authorization] => NTLM TlRMTVN... [long base64 code]
[Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
[User-Agent] => Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
[Accept-Encoding] => gzip, deflate, sdch
[Accept-Language] => de,de-DE;q=0.8,en;q=0.6,en-US;q=0.4

所以在我看来,会发生某种 NTLM 身份验证。如果我刷新站点,授权条目就会消失(可能是因为它已完成)。

Apache 服务 运行 在有效的域用户下(两台服务器上相同)。

我找到了这个 thread,但我没有在旧服务器上使用身份验证脚本 所以我想我在新服务器上不需要一个。

服务器和我的本地机器都在我们公司int运行等。我是否需要在某处定义我们的代理(通常不需要代理来访问本地服务器)或活动目录?

我担心这可能是一个非常特殊的问题,但也许你可以指出正确的方向或者知道我还能做些什么来找到 HTTP 代码 401 的原因。

感谢任何帮助。提前致谢!

编辑 2015-06-02,09:40上午

我找到了 this module,但它似乎只适用于 Apache 2.4 32 位。

编辑 2015-06-02,09:51上午

当我尝试通过网络浏览器从旧服务器访问新服务器上的 test.txt 时,系统要求我提供用户名和密码。然后,当我输入 Apache 服务 运行s 所在的同一用户时,我可以访问该文件。查看 access.log 显示以下内容:

[IP address server1] - - [02/Jun/2015:09:49:23 +0200] "GET /test.txt HTTP/1.1" 401 381
[IP address server1] - apacheuser [02/Jun/2015:09:49:23 +0200] "GET /test.txt HTTP/1.1" 200 -

Apache 服务器的行为完全正确,函数 get_headers() 没有发送正确的身份验证,因此服务器以 HTTP 代码 401 响应。

它在旧服务器上运行的原因可以在 httpd.conf 中找到。在那里我为每个子目录而不是整个 htdocs 目录定义了 SSPI 选项。新服务器上所需的文件在目录 wshelper 中,所以我将其放在新服务器上的 httpd.conf 中:

<Directory "c:/Apache24/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
    AuthName "mycompany_proxy.loc"
    AuthType SSPI
    SSPIAuth on
    SSPIAuthoritative on
    SSPIDomain mycompany_proxy.loc
    SSPIOmitDomain on
    SSPIOfferBasic on
    SSPIBasicPreferred on
    SSPIOfferSSPI on
    SSPIMSIE3HACK on
    require valid-user
</Directory>

# List all subdirectories which need to be accessible without authentication
<Directory "c:/Apache24/htdocs/wshelper">
    Satisfy Any
    Allow from all
</Directory>