简体   繁体   English

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

[英]Add header to all* HTTP requests on a machine

I need to be able to append an HTTP header (or modify the user agent string) sent by most HTTP requests leaving a PC. 我需要能够附加大多数离开PC的HTTP请求发送的HTTP标头(或修改用户代理字符串)。

By most, I mean anything inside Internet Explorer, as well as anything coming from a .NET application. 大多数情况下,我指的是Internet Explorer中的任何内容,以及来自.NET应用程序的任何内容。

I've already acoomplished the Internet Explorer side of things by writing a BHO, but that BHO won't intercept requests made by ClickOnce controls loaded into IE, which is another requirement. 我已经通过编写BHO来简化了Internet Explorer的工作,但是BHO不会拦截加载到IE中的ClickOnce控件发出的请求。

The .NET applications in my case are all using WebRequest.Create to made their requests. 以我为例,.NET应用程序都使用WebRequest.Create发出请求。

Is this possible? 这可能吗? I'm hoping I get inject some code into the System.Net stack someplace. 我希望我可以将代码插入到System.Net堆栈中的某个地方。

A proxy was one possibility, but it has proven difficult to create a proxy that doesn't perform like hell. 代理是一种可能,但是事实证明创建一个性能不如地狱的代理很困难。 HTTPS traffic is another problem. HTTPS流量是另一个问题。

Ok. 好。 I figured this out. 我想通了。

I created a custom web request module that explicitly sets the user agent of the HttpWebRequest before it's returned by the WebRequest.Create factory. 我创建了一个自定义Web请求模块,该模块在WebRequest.Create工厂返回之前显式设置HttpWebRequest的用户代理。

First, create a class that implemented IWebRequestCreate: 首先,创建一个实现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;
    }
}

You'll need to sign this assembly and add it to the GAC. 您需要签署该程序集并将其添加到GAC。

Now in the machine.config on your machine, add the following configuration section: 现在,在您计算机上的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>   

Now whenever somebody calls WebRequest.Create, they'll get an HttpWebRequest with the user agent string already set. 现在,每当有人调用WebRequest.Create时,他们都会获得一个带有已设置用户代理字符串的HttpWebRequest。


I also attempted to create a custom class that inherited from HttpWebRequest, but this was tricky because there was no default public constructor. 我还尝试创建一个从HttpWebRequest继承的自定义类,但这很棘手,因为没有默认的公共构造函数。 The only public contructor was an obsolete implementation of ISerializable. 唯一的公共构造函数是ISerializable的过时实现。

I successfully got my dervied class to be used with the ISerializable constructor, but the resulting "pseudo-hydrated" object wasn't in a valid state, likely due to the fact the ISerializable implementation is obsolete and hasn't been maintained by Microsoft. 我成功地将我的派生类与ISerializable构造函数一起使用,但是生成的“伪水合”对象不是处于有效状态,这可能是由于ISerializable实现已过时并且没有由Microsoft维护的事实。

Still, it's possible that one could make this work if they investigate the errors encountered when using it in a bit more detailed. 尽管如此,如果他们更详细地调查使用它时遇到的错误,就有可能使这项工作奏效。 Specifically, there are issues with ServicePoint related access. 具体来说,与ServicePoint相关的访问存在问题。 Using reflection, one might be able to get the thing working. 使用反射,也许可以使事情正常运行。 Here is my implementation for reference: 这是我的实现以供参考:

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM