添加标题,一台机器上的所有*的HTTP请求一台、标题、机器上、HTTP

2023-09-03 04:29:24 作者:巴勒蒙干

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

I need to be able to append an HTTP header (or modify the user agent string) sent by most HTTP requests leaving a PC.

根据大多数,我的意思是什么在Internet Explorer,以及从任何.NET应用程序来了。

By most, I mean anything inside Internet Explorer, as well as anything coming from a .NET application.

我已经acoomplished物联网浏览器端通过编写BHO,但BHO不会拦截加载到IE浏览器,这是另一项要求ClickOnce的控制提出了要求。

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.

在我的情况下,.NET应用程序都使用WebRequest.Create到了他们的请求。

The .NET applications in my case are all using WebRequest.Create to made their requests.

这可能吗?我希望我得到注入一些code到System.Net堆栈的某个地方。

Is this possible? I'm hoping I get inject some code into the System.Net stack someplace.

一个代理是一种可能性,但它已被证明很难创建一个不喜欢地狱进行代理。 HTTPS流量是另一个问题。

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.

推荐答案

确定。我想通了这一点。

Ok. I figured this out.

我创建了一个明确设置HttpWebRequest的用户代理之前,它是由类向WebRequest.Create工厂返回一个自定义的web请求模块。

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.

首先,创建实施IWebRequestCreate类:

First, create a class that implemented 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。

You'll need to sign this assembly and add it to the GAC.

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

Now in the machine.config on your machine, add the following configuration section:

<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的与用户代理字符串已经设置。

Now whenever somebody calls WebRequest.Create, they'll get an HttpWebRequest with the user agent string already set.

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

I also attempted to create a custom class that inherited from HttpWebRequest, but this was tricky because there was no default public constructor. The only public contructor was an obsolete implementation of ISerializable.

我顺利地拿到了我的dervied类要与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.

不过,这是可能的,如果他们调查时,在更详细一点使用它遇到的错误之一可能使这项工作。具体地,存在与的ServicePoint相关的访问的问题。使用反射,人们或许能得到的东西的工作。下面是我的实现,以供参考:

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