System.Net.WebClient无法与Windows身份验证一起使用。

12

我正在尝试在WinForms应用程序中使用System.Net.WebClient上传文件到一个仅支持Windows身份验证的IIS6服务器。

WebClient myWebClient = new WebClient();
myWebClient.Credentials = new System.Net.NetworkCredential(@"boxname\peter", "mypassword"); 
byte[] responseArray = myWebClient.UploadFile("http://localhost/upload.aspx", fileName);

我收到了一个“远程服务器返回错误:(401)未经授权”的错误,实际上是401.2。

客户端和IIS都在同一台Windows Server 2003开发机上。

当我尝试在Firefox中打开页面并输入与代码中相同的正确凭据时,页面会出现。 然而,在使用IE8时,我收到了相同的401.2错误。

尝试使用Chrome和Opera它们都能正常工作。

在IE Internet选项中,我已启用“启用集成Windows身份验证”。

安全事件日志有一个失败的审核:

Logon Failure:
    Reason:     An error occurred during logon
    User Name:  peter
    Domain:     boxname
    Logon Type: 3
    Logon Process:  ÈùÄ
    Authentication Package: NTLM
    Workstation Name:   boxname
    Status code:    0xC000006D
    Substatus code: 0x0
    Caller User Name:   -
    Caller Domain:  -
    Caller Logon ID:    -
    Caller Process ID:  -
    Transited Services: -
    Source Network Address: 127.0.0.1
    Source Port:    1476

我使用了 Process Monitor 和 Fiddler 进行调查,但是没有发现任何问题。

为什么这对第三方浏览器有效,但对 IE 或 System.Net.WebClient 无效?


将IIS中的单一身份验证方法从集成Windows更改为基本身份验证后,它可以正常工作,但这并不能解决我的问题,因为我无法在生产服务器上更改该设置。 - Peter Hahndorf
我使用了IIS“身份验证和访问控制诊断工具”来监视进程,并将Firefox的日志与IE的进行比较。一切看起来都很好,直到NTLM挑战/响应失败,但它也没有给我任何线索为什么会这样。 - Peter Hahndorf
我进行了更多的测试:上述的2003服务器实际上是Virtual PC中的虚拟机,在使用主机上的IE时,我可以进行身份验证,但在客户机上使用IE时却不能。然而,当使用站点的IP地址而不是通过hosts文件设置的主机名时,使用客户机的IE是有效的。这里有些问题!我很高兴它不是在生产服务器上出现的。 - Peter Hahndorf
4个回答

21
我曾经遇到过类似的问题,当使用集成/ NTLM安全性访问主机时,只有在通过机器名或本地主机访问主机时才能正常工作。实际上,这是Windows中一个[糟糕的]文档功能,旨在防止“反射攻击”。
基本上,您需要在尝试访问服务器的计算机上创建一个注册表键,并将您要访问的域添加到白名单中。每个主机名/ FQDN都需要在自己的行中 - 没有通配符,且名称必须完全匹配。从KB文章中获得以下信息:
  • 单击“开始”,单击“运行”,键入regedit,然后单击“确定”。
  • 在注册表编辑器中,找到并单击以下注册表键: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
  • 右键单击 MSV1_0,指向新建,然后单击多字符串值。
  • 键入 BackConnectionHostNames,然后按 ENTER。
  • 右键单击 BackConnectionHostNames,然后单击修改。
  • 在数值数据框中,键入本地计算机站点的主机名或主机名,然后单击“确定”。
  • 退出注册表编辑器,然后重新启动计算机。

http://support.microsoft.com/kb/956158/en-us


3
如果我能点赞10次,我就会这么做。结束了我三天的苦思冥想和谷歌搜索。 - DancesWithBamboo
1
上面的链接已经失效。请查看https://support.microsoft.com/en-us/help/896861/you-receive-error-401-1-when-you-browse-a-web-site-that-uses-integrate。它还包括另一个设置:创建并设置DWORD值HKLM \ SYSTEM \ CurrentControlSet \ Services \ lanmanserver \ parameters \ DisableStrictNameChecking = 1。 - David I. McIntosh

4

您是否尝试过...

new NetworkCredential( "peter", "password", "boxname" );

您也可以尝试...
var credCache = new CredentialCache();
credCache.Add( new Uri ("http://localhost/upload.aspx"),
                 "Negotiate",
                 new NetworkCredential("peter", "password", "boxname"));
wc.Credentials = credCache;

根据这里的内容,可能是IIS配置错误。请将上面的“Negotiate”替换为“Basic”,并检查网站的IIS配置。此外,这里还有一些可能的原因。


还尝试了“Negotiate”版本,结果相同。令我困惑的是它在IE中也无法工作。 - Peter Hahndorf

1

尝试进入IE选项并将站点显式添加到内部网区域。然后重新运行程序。您也不应该从管理员登录运行程序。这可能会触发Internet Explorer的增强安全配置

这可能解释了为什么您可以使用Firefox和Opera访问该站点,但不能使用IE或WebClient。


0

在不知道您的IIS部署情况的前提下,并假设您已经在IIS中设置了正确的上传授权规则(例如,在尝试上传内容的正确目录上设置了正确的allow* ACL),我首先会尝试将UseDefaultCredentials设置为true,而不是显式地设置凭据。(也许您认为您正在使用设置的凭据访问服务器,但事实并非如此?如果这样可以工作,那么这是可能的。)

这是一个非常常见的场景,所以我会关注您尝试上传文件的目录的IIS授权规则,以及该目录上的实际ACL。例如,您的站点是否正在模拟用户?如果是,则必须在该目录上具有实际的ACL,否则就是应用程序池正在运行的任何帐户。


我认为这不是ACL问题,因为它没有到达那一步,进程监视器上也没有显示任何目标目录的活动。 - Peter Hahndorf
刚试了一下使用UseDefaultCredentials,但还是失败了。我需要让它使用非默认凭据来工作,因为在生产环境中客户端和服务器机器上的Windows用户是不同的。 - Peter Hahndorf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接