我有几个使用集成 Windows 身份验证和 Kerberos 委派的经典 ASP 站点。
它们在实时服务器上运行良好(最近已迁移到 Server 2008/IIS7 服务器),但在我的开发 PC 或开发服务器上无法完全运行。两台机器上的 IIS 都是通过从旧机器导出的 IIS Web 部署工具包配置的;部署工作并不完美,我不得不进行一些调整才能使网站正常运行。
当在任意一台机器上本地访问应用程序时,它们都可以正常工作;当从另一台机器访问时,系统会提示用户输入用户名/密码对话框,无论你输入什么,最终都会导致401(未授权)错误。
我尝试将这些机器的配置与类似的实时服务器(所有服务器都运行良好)进行比较,它们看起来通常具有可比性(因为所有实时服务器都尚未使用 IIS7.5(Windows 7/Server 2008 R2)。
这些应用程序运行在一个公共应用程序池中,该池使用一个特殊的域用户作为其身份 - 此用户在实时和开发机器上具有类似的权限。在 IIS6 平台上,为了启用 Kerberos 委派,我需要为该用户设置一些 SPN,并且它们仍然存在(尽管由于内核模式身份验证,我认为 IIS7+ 不再需要它们),
此外,此帐户已在 Active Directory 中启用 Kerberos 委派,我处理的每台机器也是如此。
我正在考虑部署可能对 IIS 配置进行了更改/未能更改,从而导致此问题的可能性。也许完全重建(减去另一次 Web 部署尝试)可以解决问题,但我宁愿修复(从而理解)当前问题。
目前有什么想法吗?
我刚刚再次尝试修复此问题,并且取得了一些进展,但尚未完全解决。
我发现如果我通过 IP 地址(而不是通过 NetBIOS 名称)访问网站,我会看到相同的对话框,只不过它接受我的凭据,因此应用程序可以正常工作 - 虽然不是完全修复,但却是一个有用的步骤。
更有趣的是,我发现如果我禁用内核模式身份验证(在IIS 管理器 > 网站 > 身份验证 > 高级设置),应用程序运行正常。我模糊的理解是,这实际上是按照 IIS7 之前的方式运行的。这是一个合理的短期解决方案,但请考虑 IIS 针对此问题给出的以下明确建议:
默认情况下,IIS 启用内核模式身份验证,这可以提高身份验证性能并防止配置为使用自定义标识的应用程序池出现身份验证问题。作为最佳做法,如果您的环境中使用 Kerberos 身份验证并且应用程序池配置为使用自定义标识,请不要禁用此设置。
显然,这不是我的应用程序应有的工作方式。那么问题是什么呢?
答案1
尝试使用其他浏览器,例如,如果您现在使用的是 IE,请尝试使用 Chrome。这可能是由于域名位于 Intranet 或受信任区域中。这可能会导致它尝试保存可能无法远程工作的凭据,具体取决于您是否来自域外。
答案2
我已经为这个问题苦苦挣扎了好几年。我偶尔能设法让它工作,但一年后服务器要搬迁,我不得不再次努力让它在新服务器上工作。
这样的时刻又来了......在努力调试这些 kerberos 问题之后,我回归基础:其他人一定经常做我尝试过的事情——他们使用了什么?
虽然有人使用我的技术,但他们显然没有遇到我遇到的问题。但有十几种方法可以解决大多数问题,所以我结合了在网上 2 或 3 个例子中找到的技术,并采用了不同的方法,这种方法似乎比我之前的方法更可靠,也不复杂,而且关键的是,它不涉及臭名昭著的 Kerberos“双跳”:
Sub Authuser()
'Swap out values enclosed in []
If Session("UID") = "" or 1 then
Dim rsUser, aUserID, aGroups, i
Dim connAD, sBase, sFilter, sAttributes, sScope, sFullCommand, rsADUserInfo, oADSysInfo
aUserID = Split(Request.servervariables("AUTH_USER"),"\")
Set connAD = Server.CreateObject("ADODB.Connection")
connAD.Provider = "ADsDSOObject"
connAD.Properties("User ID") = "[MyDomain]\[MyDomainUser]" ' ### remember to make sure this user has rights to access AD
connAD.Properties("Password") = "[password]"
connAD.Properties("Encrypt Password") = true
connAD.Open
sBase = "<LDAP://DC=[MyDomain], DC=[MyDomainExt]>"
sFilter = "(sAMAccountName=" & aUserID(1) & ")"
sAttributes = "cn, mail, company, givenName, sn, ADsPath, name, sAMAccountName, telephoneNumber, memberof"
sScope = "subtree"
sFullCommand = sBase & ";" & sFilter & ";" & sAttributes & ";" & sScope
set rsUser = Server.CreateObject("ADODB.Recordset")
set rsUser = connAD.Execute(sFullCommand)
If not rsUser.EOF then
Session("UID") = aUserID(1)
Session("Name") = rsUser("cn")
Session("Email") = rsUser("mail")
If IsArray(rsUser.Fields(9)) Then
aGroups = rsUser.Fields(9)
For i = LBound(aGroups) To UBound(aGroups)
If InStr(1, aGroups(i), "[MyUsersGroup]", 1) Then
Session("Auth") = 1
End If
If InStr(1, aGroups(i), "[MyAdminGroup]", 1) Then
Session("Admin") = 1
End If
Next
Else
Response.Write "No groups<BR>"
Session("Auth") = 1
Session("Admin") = 1
End If
Else
Response.Write "User not recognised in AD<br>"
End if
connAD.Close
set rsUser = Nothing
Set connAD = Nothing
End If
End Sub