我有以下PHP代码在IIS下运行:
$serverName = "someServer'someServer";
$connectionInfo = array( "Database"=>"SOME_DB");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn ) {
echo "Connection established.<br />";
}else{
echo "Connection could not be established.<br />";
die( print_r( sqlsrv_errors(), true));
}
当我尝试访问该页面时,我得到错误:
[Microsoft][SQL Server Native Client 10.0][SQL Server]用户"NT AUTHORITY''ANOYMOUS LOGON"登录失败。
这是令人困惑的,因为这里的文档说"将使用Windows身份验证尝试连接"。
这个流程是:
- 在
workstation1
上使用x
Windows帐户的用户访问server1
上托管的此网站 server1
执行上面的PHP代码,并尝试使用y
Windows帐户从server2
检索数据(y
在IIS设置中的应用程序池->标识下定义)- Windows帐户
y
有权访问数据库
IIS池在Windows域用户"domainadm"下运行,该用户可以访问SOME_DB
数据库及其所在的服务器。
为什么它试图匿名进行身份验证,我如何解决这个问题,使它在IIS池运行的用户下运行?
在php.ini中:
fastcgi.impersonate = 1;
检查IIS中的"身份验证"部分,我只有"匿名身份验证"或"ASP.NET模拟"选项。没有Windows身份验证?
"匿名"当前已启用,这会出现上面的错误。如果我切换到ASP.NET,我在访问页面时会出现以下错误:
500-内部服务器错误。您正在查找的资源出现问题,无法显示。检测到一个ASP.NET设置不适用于集成托管管道模式。
我更新的web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Detailed" />
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
<system.web>
<identity impersonate="true" />
<authentication mode="Windows" />
<customErrors mode="Off" />
<compilation debug="true" />
</system.web>
</configuration>
问题是,尽管您以AppPool标识运行,IIS仍在匿名向SQL发送连接。要解决此问题,您必须启用从web服务器(server1)到SQL服务器(server2)的匿名连接。
在SQL server上,为<YourDomain>'server1$
创建登录名,并在用户映射选项卡下为Some_DB
分配适当的权限。例如,授予此帐户db_datareader
和db_datawriter
权限,您应该能够连接并成功完成CRUD操作。为了进行测试,您可能只想暂时授予此登录db_owner
对Some_DB
的权限,以确保SQL权限没有问题。
关于PHP fastcgi.impersonate
设置,我相信您可以将其设置为0/false,因为在这种情况下这无关紧要。
在IIS中的身份验证部分,启用Windows身份验证和ASP.NET模拟。
这些将是IIS中将启用的唯一身份验证类型。
在web.config文件中,您将需要以下内容(如果Windows没有出现,这应该可以解决问题):
<system.web>
<identity impersonate="true" />
<authentication mode="Windows" />
identity.impersonate的原因是您需要它来模拟通过windows登录的用户凭据。
一旦用户通过身份验证,就可以使用匿名身份验证来访问数据库。
例如,为了证明上述方法的有效性,请在数据库中转到Security-Logins on SQL Server并添加登录名。
添加:NT授权''匿名登录
并为其分配dboOwner角色以确保其正常工作。
执行以上操作将证明IIS的设置方式没有其他冲突,例如不正确的web.config条目。
请确保应用程序池在集成模式下运行,并且在数据库连接字符串中具有integrated Security=true。
如果需要,您可以分配一个不同的帐户,例如您的"domainadm"帐户,一个运行应用程序池的服务帐户。但是,如果用户不在同一个域上,可能会出现问题,以及由于服务器/帐户的配置方式而可能出现的其他问题,这些问题可能会导致此操作失败。但是,尝试以上步骤将使其运行,以便在必要时诊断这些问题。
此处关于Windows身份验证或模拟的建议不适用于您的情况。Windows身份验证将使客户端计算机"x"使用前端"server1"进行身份验证,模拟将用于将凭据"x"转发到SQL"server2"。这将要求每个使用该网站的用户都有SQL访问权限。相反,您希望匿名访问您的网站,并让网站管理自己对SQL的访问。
问题摘要:匿名身份验证的默认用户是IUSR,无论您的应用程序池设置如何。当它尝试连接到网络资源时,它会验证为"NT AUTHORITY''Anonymous LOGIN"。显然,当试图锁定访问时,这不是很有用。
你可以在这里看到这一点:http://www.iis.net/learn/get-started/planning-for-security/understanding-built-in-user-and-group-accounts-in-iis
注意:IUSR帐户在网络上匿名操作的方式与LOCALSERVICE类似。NETWORKSERVICE和LOCALSYSTEM帐户可以充当计算机标识,但IUSR帐户不能,因为它需要提升用户权限。如果您需要匿名帐户才能在网络上拥有权限,则必须创建一个新的用户帐户,并手动设置用户名和密码,就像过去进行匿名身份验证一样。
更多信息可在此处找到:http://www.iis.net/learn/get-started/whats-new-in-iis-7/changes-in-security-between-iis-60-and-iis-7-and-above
解决方案:转到"身份验证"部分,选择"匿名身份验证",然后单击"编辑…"。。。,并从"特定用户:IUSR"更改为"应用程序池标识"。这应该会迫使网站使用您为应用程序池设置的帐户。
完成后,如果您使用默认的应用程序池设置"应用程序池标识",您的应用程序将尝试使用SQL作为DOMAIN''MACHINENAME进行身份验证。