【问题标题】:Add header to all* HTTP requests on a machine将标头添加到机器上的所有* HTTP 请求
【发布时间】:2013-12-11 03:09:45
【问题描述】:

我需要能够附加大多数 HTTP 请求离开 PC 时发送的 HTTP 标头(或修改用户代理字符串)。

大多数情况下,我指的是 Internet Explorer 中的任何内容,以及来自 .NET 应用程序的任何内容。

我已经通过编写 BHO 完成了 Internet Explorer 方面的工作,但是 BHO 不会拦截加载到 IE 中的 ClickOnce 控件发出的请求,这是另一个要求。

在我的例子中,.NET 应用程序都使用 WebRequest.Create 来发出请求。

这可能吗?我希望我能在 System.Net 堆栈的某个地方注入一些代码。

代理是一种可能性,但事实证明,要创建一个性能不如地狱的代理是很困难的。 HTTPS 流量是另一个问题。

【问题讨论】:

  • 除了代理之外别无他法。您说对于大多数 HTTP 请求,有什么限制?您想捕捉哪些的请求?其他浏览器(Firefox、Chrome、...)呢?
  • 我在第二段中解释了我所说的“大多数”是什么意思。
  • 好的 - 不清楚你的意思只是 IE;包含 IE 似乎很奇怪,但不关心其他浏览器,所以只是检查是设计使然,而不是偶然。
  • 不。不是意外。这主要用于仅支持 IE 的内部应用程序。
  • 您的 CustomHttpRequestCreator 是否拦截了来自 IE 的所有流量并添加了该标头?

标签: .net http


【解决方案1】:

好的。我想通了。

我创建了一个自定义 Web 请求模块,它在 WebRequest.Create 工厂返回之前显式设置 HttpWebRequest 的用户代理。

首先,创建一个实现 IWebRequestCreate 的类:

public class CustomHttpRequestCreator : IWebRequestCreate
{
    public CustomHttpRequestCreator(){}

    public WebRequest Create(Uri uri)
    {
        HttpWebRequest webRequest = Activator.CreateInstance(typeof(HttpWebRequest),
                                        BindingFlags.CreateInstance | BindingFlags.Public |
                                        BindingFlags.NonPublic | BindingFlags.Instance,
                                        null, new object[] { uri, null }, null) as HttpWebRequest;

        webRequest.UserAgent = "OMG IT WORKED!";
        return webRequest;
    }
}

您需要签署此程序集并将其添加到 GAC。

现在在您机器上的 machine.config 中,添加以下配置部分:

<system.net>
    <webRequestModules>
        <remove prefix="http:"/>
        <remove prefix="https:"/>
        <add prefix="http:" type="HttpWebRequestTest.CustomHttpRequestCreator, HttpWebRequestTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4ba7a6b9db5020b7" />
        <add prefix="https:" type="HttpWebRequestTest.CustomHttpRequestCreator, HttpWebRequestTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4ba7a6b9db5020b7" />
    </webRequestModules>
</system.net>   

现在每当有人调用 WebRequest.Create 时,他们都会得到一个已经设置好用户代理字符串的 HttpWebRequest。


我还尝试创建一个继承自 HttpWebRequest 的自定义类,但这很棘手,因为没有默认的公共构造函数。唯一的公共构造函数是 ISerializable 的过时实现。

我成功地让我的派生类与 ISerializable 构造函数一起使用,但生成的“伪水合”对象未处于有效状态,这可能是因为 ISerializable 实现已过时且尚未维护由微软提供。

不过,如果他们更详细地调查使用它时遇到的错误,则有可能完成这项工作。具体来说,与 ServicePoint 相关的访问存在问题。使用反射,一个人可能能够让事情正常工作。这是我的实现供参考:

public class CustomHttpWebRequest : HttpWebRequest
{
    public CustomHttpWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }

    internal CustomHttpWebRequest(Uri uri) : base(BuildSerializationInfo(uri), new StreamingContext())
    {
        this.UserAgent = "OMG IT WORKED! (Constructor)";
    }

    private static SerializationInfo BuildSerializationInfo(Uri uri)
    {
        HttpWebRequest webRequest = Activator.CreateInstance(typeof(HttpWebRequest),
                                        BindingFlags.CreateInstance | BindingFlags.Public |
                                        BindingFlags.NonPublic | BindingFlags.Instance,
                                        null, new object[] { uri, null }, null) as HttpWebRequest;

        var serializationInfo = new SerializationInfo(typeof(HttpWebRequest), new System.Runtime.Serialization.FormatterConverter());
        ((ISerializable)webRequest).GetObjectData(serializationInfo, new StreamingContext());
        return serializationInfo;
    }

    public override WebResponse GetResponse()
    {
        this.UserAgent = "OMG IT WORKED!";
        return base.GetResponse();
    }

    public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
    {
        this.UserAgent = "OMG IT WORKED ASYNC!";
        return base.BeginGetResponse(callback, state);
    }
}

【讨论】:

  • 这既令人敬畏又令人恐惧。
猜你喜欢
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多