5

我有一个经典 ASP 站点的 VB6 后端。然后,该 VB 使用 MSXML2.XMLHTTP 调用同一服务器上的 Web 服务。这适用于我们所有的服务器,但只有一个。如果我将 Web 服务站点设置为接受匿名登录,它将起作用,但是如果我强制仅集成安全 MSXML 返回访问被拒绝错误。

我在这里使用示例中的代码。

Set objDom = CreateObject("MSXML2.DOMDocument")
Set objXmlHttp = CreateObject("MSXML2.XMLHTTP")

' Load XML
objDom.async = False
objDom.loadXML XmlBody

' Open the webservice
objXmlHttp.Open "POST", AsmxUrl, False

' Create headings
objXmlHttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
objXmlHttp.setRequestHeader "SOAPAction", SoapActionUrl

' Send XML command
objXmlHttp.send objDom.xml

编辑:按照 AnthonyWJones 的建议,我查看了清单,但它仍然无法正常工作。使用 Fiddler 它显示一个带有 401 响应的请求。身份验证选项卡显示:

No Proxy-Authenticate Header is present.
WWW-Authenticate Header is present: Negotiate
WWW-Authenticate Header is present: NTLM

我确实注意到了一个奇怪的行为。当我使用登录到远程桌面的用户的凭据调用该网站时,它将起作用。我得到谈判,挑战,然后是200,它会起作用。任何想法为什么当用户通过远程桌面登录而不是其他时间时这会起作用?

4

3 回答 3

3

我猜你是依靠底层的 WinINET HTTP 堆栈在使用 Windows 集成安全性受到服务器挑战时向服务器提供当前用户凭据。

只有当 WinINET 认为主机服务器位于 Intranet 区域时,它才会默认执行此操作。即使这样,用户的 Intranet 区域安全设置也可能已被调整为不允许这样做。

当您以运行 VB6 应用程序的同一用户身份登录时,请尝试使用客户端计算机上的浏览器访问该站点。它认为服务器位于哪个区域?如果它不是 Intranet,则需要将主机添加到属于该区域的站点列表中。当您在那里时,打开区域安全设置并向下滚动到用户身份验证类别。登录应配置为“仅在 Intranet 区域自动登录”。

编辑:根据您的评论,这些东西配置正确。我会做的几件事是:-

  1. 检查服务器是否严格配置为仅接受 Windows 集成安全性。
  2. 检查机器上的代理设置,权限被拒绝是代理服务器的问题吗?
  3. 使用 ProgID“MSXML2.XMLHTTP.3.0”确保使用正确版本的 MSXML dll(某些其他第三方应用程序的安装可能会损坏注册表,导致使用旧版本的 MSXML)。
  4. 在机器上安装Fiddler并在 VB6 应用程序尝试调用时观看 http 对话。是否有单个 401 响应?WinINET 是不是使用了用户凭据?有 3 401 个响应吗?WinINET 已尝试使用当前用户凭据,但服务器不接受它们。

至此,我们进入了系统管理领域。例如,如果提琴手跟踪显示尝试进行身份验证没有使用 NTLM,那么它使用的是 Kerberos 身份验证,请检查服务器和客户端的时钟设置是否在 5 分钟内彼此以及域控制器。

检查服务器事件日志,是服务器无法联系域控制器。

在只有 Windows 集成安全性的服务器上放置一个简单的 .htm 并尝试从浏览器中访问它,是否成功?

于 2009-07-29T13:43:05.123 回答
3

回复 Ryan 可能为时已晚,但其他人可能有同样的问题,所以我会发布这个:我有一个开发人员遇到了同样的问题MSXML2.XMLHTTP。问题是我有从很久以前就可以做到这一点的样本,所以我知道它曾经可以工作,但现在不行……也许是最近引入的错误?我们依靠WinINET堆栈自动检测本地 Intranet,然后堆栈愿意进行 Windows 集成。该站点位于代理绕过列表中,默认选项将其放入本地 Intranet。事实上,当您浏览该站点并转到“安全设置”选项卡时,您会看到“本地 Intranet”已突出显示,因此它似乎可以正常工作。然而,MSXML2.XMLHTTP仍然不愿意集成 Windows ... 除非您使用“安全”选项卡上的“站点/高级”按钮直接将站点添加到本地 Intranet。

所以我的结论是,堆栈中现在存在某种错误WinINET,它将自动检测到的本地 Intranet 站点与直接添加到站点列表中的站点区别对待。有趣的是,当浏览到该站点时,一切正常,并且自动使用 Windows 集成(即使没有直接添加到站点):它只是通过程序访问MSXML2.XMLHTTP不起作用。

最后,这不是我们最终做的事情:我们MSXML2.ServerXMLHTTP.6.0改为使用。该堆栈(WinHTTP_堆栈中的 IE 代理设置。缺点是每台客户端机器上的额外配置(这是一个胖客户端 VB 应用程序)。我们选择做的是将以下内容放在发送之前:ProxyCfgNETSHWinHTTP

HTTP.SetProxy 2, "myproxy.mydomain.com", "*.mydomain.com"

由于您将访问 mydomain 站点,您可能会认为您可以改为使用HTTP.SetProxy 0, 来绕过代理,但这不起作用。必须告诉堆栈:“我有一个代理,但为我的域绕过它,顺便说一句,我要去的站点在那个域中,所以它是本地 Intranet”。

于 2009-12-03T21:01:57.973 回答
0

在查看了 AnthonyWJones 建议的所有内容后,我发现我可以通过以下方式使用基本身份验证:

 objXmlHttp.Open "POST", AsmxUrl, False, UserName, Password

如果我允许集成安全性,它将尝试协商但随后失败并出现 401,但如果仅允许基本身份验证,它将连接。这不是我的首选,但它是比允许匿名访问更好的解决方法。我将把这个开放一段时间,以防有人可以解释如何让集成安全工作,然后给 AnthonyWJones 接受的答案,因为他的清单很好,让我找到了这个其他选项。

Fiddler 在找出这一切方面非常有帮助。

于 2009-07-30T20:30:20.247 回答