0

好的,简单的问题,但在我开始之前需要一些解释。

我正在尝试使用 System.Net.WebClient (或 WebRequest,相同的结果)通过代理服务器下载 https 页面。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    static class Program
    {
        static void Main(string[] args)
        {
             var wc = new WebClient();
             wc.Proxy = new WebProxy("MyProxyAddress") { UseDefaultCredentials = true };
             wc.Headers.Add("xyz", "abc");

            try
            {
                 Console.WriteLine(wc.DownloadString("https://www.google.co.nz"));
            }
            catch (WebException wex)
            {
                if (wex.Response != null)
                    using (var reader = new StreamReader(wex.Response.GetResponseStream()))
                        Console.WriteLine(reader.ReadToEnd());
            }
        }
    }
}

如果我此时启动 Fiddler,我可以看到请求如下所示。请注意,我已将 Fiddler 设置为需要代理身份验证。

CONNECT www.google.co.nz:443 HTTP/1.1
Host: www.google.co.nz
Proxy-Connection: Keep-Alive

回应将是

HTTP/1.1 407 Proxy Auth Required
Connection: close

,正如预期的那样。如果我将地址从 https://... 更改为 http://...,我会得到这个。请注意,现在显示 xyz 标头

GET http://www.google.co.nz/ HTTP/1.1
xyz: abc
Host: www.google.co.nz
Proxy-Connection: Keep-Alive

一切都很好,除非我正在通过的代理需要用户代理。包括我的 User-Agent 在内的所有标头都从请求中删除,因此代理拒绝了该请求。如果我将 Fiddler 配置为强制将 User-Agent 标头放入请求中,则一切正常。

那么,为什么我的标头没有包含在 CONNECT 请求中?这是一个 MS 错误,还是我错过了什么?

4

1 回答 1

0

通过 Web 代理的 HTTPS 的工作方式如下:

  1. 客户端向代理发送CONNECT请求 - 这就是您在 Fiddler 中看到的内容。
  2. Proxy 同意连接、返回200 CONNECTED,现在充当无逻辑数据泵
    • 如果代理需要身份验证,它将返回407 Proxy Auth Required,并且客户端将使用正确的代理身份验证发出相同的CONNECT请求。
  3. 客户端现在可以通过盲目地抽取数据的代理与真实服务器直接通信。
    • 通常,客户端会执行 HTTPS 会话协商,然后通过加密会话发送“真正的”HTTP 请求。

我不是 100% 熟悉WebClient,但我假设添加的标头仅适用于“真实”HTTP 请求(上面的 3)。您也许可以对您的WebProxy实例做一些事情,尽管我在那里也没有找到任何解决方案。

于 2012-12-12T09:38:19.033 回答