为计算机上的所有* HTTP请求添加标头

时间:2012-02-09 19:43:08

标签: .net http

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:6)

确定。我想出了这个。

我创建了一个自定义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的过时实现。

我成功地将我的dervied类与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);
    }
}