8

更新:
如果您刚刚遇到这个问题,一般的要点是我正在尝试通过代理创建一个 HttpWebRequest,并且我从我们奇怪的代理服务器获得了 407。IE、Firefox、Chrome 都成功地协商代理,Adobe Air 应用程序也是如此。谷歌浏览器网络安装程序实际上失败可能很重要,我们必须使用离线安装程序。

多亏了 Ian 的链接,我才得以进入下一阶段。它现在正在向代理发送一个令牌,但是第三阶段没有通过,所以带有用户名/密码哈希的请求没有被 .NET 发送,因此没有返回 HTML。

我在用:

  • IE6 用户代理
  • Windows 7的
  • Scansafe 代理
  • .NET 3.5

这是等同于以下日志的最新代码:

HttpWebRequest request = HttpWebRequest.Create("http://www.yahoo.com") as HttpWebRequest;
IWebProxy proxy = request.Proxy;
// Print the Proxy Url to the console.
if (proxy != null)
{
    // Use the default credentials of the logged on user.
    proxy.Credentials = CredentialCache.DefaultCredentials;
}
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.Accept = "*/*";

HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream stream = response.GetResponseStream();

例外

WebException (407) 需要身份验证。

正在使用的代理

代理客户端是我们服务器机房中的Scansafe硬件设备,它(一旦通过 NTLM 验证)然后将您的 HTTP 流量定向到其服务器以过滤流量。

System.Net 跟踪输出

IE 成功协商代理

解决方案

我还没有真正找到解决方案,但感谢 Feroze 和 Eric,我找到了一种解决方法,并发现实际的代理(而不是它的配置)是主要问题。这可能是 3 个变量的一个模糊问题:.NET HttpWebRequest 的实现、Windows 7,当然还有我们机架中的 Scansafe 硬件客户端;但如果没有 MSDN 支持请求,我将不会发现。

4

8 回答 8

8

如果要为代理设置凭据,您不应该在 request.Proxy 对象而不是 request 对象上设置凭据吗?

http://msdn.microsoft.com/en-us/library/system.net.webproxy.credentials.aspx

另外,请记住,您需要发出 HTTP/1.1 请求(或从技术上讲,任何使用 Keep-Alive 的请求)才能成功使用 NTLM/Negotiate 身份验证。

(如果您还没有查看的话,Fiddler 的“Auth”检查器将为您分解 NTLM 身份验证 blob。)

于 2009-09-22T05:17:27.550 回答
6

我编写了一个实用程序来解码在 IE 和 HttpWebRequest 会话中发送的 NTLM blob。

当我查看 HttpWebRequest 和 IE 时,它们都从服务器请求 56 位和 128 位加密。这是使用 HttpWebRequest 的会话转储

==== Type1 ----
Signature: NTLMSSP
Type: 1
Flags: E20882B7
NTLMSSP_NEGOTIATE_56
NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP_NEGOTIATE_128
RESERVED2
RESERVED3
RESERVED4
NTLMSSP_REQUEST_NON_NT_SESSION_KEY
NTLMSSP_TARGET_TYPE_DOMAIN
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
NTLMSSP_NEGOTIATE_DATAGRAM
NTLMSSP_REQUEST_TARGET
NTLM_NEGOTIATE_OEM
NTLMSSP_NEGOTIATE_UNICODE)
Domain :
Workstation:
==== Type2 ----
Signature: NTLMSSP
Type: 2
Flags: 201
NTLMSSP_NEGOTIATE_56
NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
Context: D32FDDCB:63507CFA

这是来自 IE 的转储:

==== Type1 ----
Signature: NTLMSSP
Type: 1
Flags: A208B207
NTLMSSP_NEGOTIATE_56
NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP_NEGOTIATE_128
NTLMSSP_REQUEST_NON_NT_SESSION_KEY
NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
NTLMSSP_TARGET_TYPE_SHARE
NTLMSSP_TARGET_TYPE_DOMAIN
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
NTLMSSP_NEGOTIATE_DATAGRAM
NTLMSSP_REQUEST_TARGET
NTLMSSP_NEGOTIATE_UNICODE)
Domain : XXXX.UK
Workstation: XXX-X31
==== Type2 ----
Signature: NTLMSSP
Type: 2
Flags: 201
NTLMSSP_NEGOTIATE_56
NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
Context: D32FDDCB:63507CFA

在 IE/HttpWebRequest 中,它们都请求 64 位和 128 位安全性。但是,对于 windows7,NTLM 的 128 位安全性已成为默认设置,否则身份验证将失败。从服务器响应中可以看出,服务器只支持 64 位加密。

以下链接讨论了另一个人遇到的类似问题。 http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/f68e8878-53e9-4208-b589-9dbedf851198

IE 工作而不是托管应用程序的原因是 IE 实际上并不请求 NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN,最终需要加密。但是,HttpWebRequest 确实请求 SEAL|SIGN。这需要 128 位加密,而 IE 初始化 NTLMSSP 的方式(没有 SEAL & SIGN),它不需要加密。因此 IE 可以工作,而 HttpWebRequest 不能。(见上面的链接)

我认为,如果您更改安全策略以允许 NTLM 进行 64 位加密,您的托管代码应用程序将正常工作。或者,要求代理供应商支持 NTLM 的 128 位加密。

希望这可以帮助。

于 2009-09-26T23:51:54.903 回答
3

我遇到了类似的问题,并使用以下博客文章中的提示来解决问题:

http://blogs.msdn.com/jpsanders/archive/2009/03/24/httpwebrequest-webexcepton-the-remote-server-returned-an-error-407-proxy-authentication-required.aspx

于 2009-09-18T10:36:20.813 回答
1

验证以下设置secpol.msc。它解决了我们的问题。

Local Security Policy 
    Local Policies
        Security Options
            Network security: Minimum session security

设置:

require 128 only for client. 

在此处输入图像描述

于 2013-03-05T16:44:08.210 回答
0

您可以尝试将 HttpWebRequest 上的 User-Agent 标头设置为与 IE8 设置的值相同的值吗?

有时,如果用户代理不是他们所期望的,服务器将无法正确挑战。

希望这可以帮助。

于 2009-09-19T03:11:13.427 回答
0

是代理分配的方式吗?

proxy.Credentials = CredentialCache.DefaultCredentials;

当我上次将代理与 HttpWebRequest 一起使用时,它的分配方式如下:

为请求分配代理:

request.Proxy.Credentials = Credentials.GetProxyCredentials();

调用方法:

    public static ICredentials GetProxyCredentials()
    {
        return new NetworkCredential(AppConstants.Proxy_username, AppConstants.Proxy_password);
    }

在 web.config 中配置代理

<system.net>
  <defaultProxy enabled="true">
    <proxy
      autoDetect="False"
      bypassonlocal="True"
      scriptLocation="http://www.proxy.pac"
      proxyaddress="http://proxy1.blah.com" />
  </defaultProxy>
</system.net>
于 2009-09-25T04:41:39.880 回答
0

它可能与您的“CredentialCache”中的内容有关。试试这个:

proxy.Credentials = new NetworkCredential("username", "pwd", "domain"); 
于 2009-09-25T14:55:36.937 回答
0

这个怎么样:

        HttpWebRequest request = HttpWebRequest.Create("http://www.yahoo.com") as HttpWebRequest;
        WebProxy proxyObject = new System.Net.WebProxy("http://10.0.0.1:8080/", true); //whatever your proxy address is

        proxyObject.Credentials = CredentialCache.DefaultCredentials;
        request.Proxy = proxyObject;

        request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
        request.Accept = "*/*";

        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
        Stream stream = response.GetResponseStream();
于 2009-09-25T21:39:09.230 回答