简体   繁体   English

如何在HttpWebRequest中设置自定义“主机”标头?

[英]How to set custom “Host” header in HttpWebRequest?

How can I set a custom Host header in HttpWebRequest? 如何在HttpWebRequest中设置自定义主机头? I know that normally this class doesn't allow you to do so but is there anyway to use reflection or something like that without actually need me to send the whole packet with TCPClient? 我知道通常这个类不允许你这样做,但无论如何使用反射或类似的东西而不需要我用TCPClient发送整个数据包?

There is a roundabout way to do this, as described here: 有一种迂回的方式来做到这一点,如下所述:

http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx

However, the next version of the framework (.NET Framework 4.0) will make it easier. 但是,下一版本的框架(.NET Framework 4.0)将使其更容易。

http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx

Hope this helps. 希望这可以帮助。

You can use this hack, designed for solve this problem in .Net 3.5 . 您可以使用此hack,专为解决.Net 3.5中的此问题而设计。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;


namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://198.252.206.16");

            FieldInfo headersFieldInfo =  request.GetType().GetField("_HttpRequestHeaders", System.Reflection.BindingFlags.NonPublic
                                                    | System.Reflection.BindingFlags.Instance
                                                    | System.Reflection.BindingFlags.GetField);

            CusteredHeaderCollection WssHeaders = new CusteredHeaderCollection("stackoverflow.com");

            headersFieldInfo.SetValue(request, WssHeaders);

            request.Proxy = null;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            StreamReader sr = new StreamReader(response.GetResponseStream());
            string result = sr.ReadToEnd();
            Console.WriteLine(result);
            Console.ReadLine();

        }
        public class CusteredHeaderCollection : WebHeaderCollection
        {
            public bool HostHeaderValueReplaced { get;private  set; }

            public string ClusterUrl { get; private set; }

            public CusteredHeaderCollection(string commonClusterUrl) : base()
            {
                if (string.IsNullOrEmpty("commonClusterUrl"))
                    throw new ArgumentNullException("commonClusterUrl");

                this.ClusterUrl = commonClusterUrl;
            }

            public override string ToString()
            {
                this["Host"] = this.ClusterUrl;
                string tmp =  base.ToString();
                this.HostHeaderValueReplaced = true;

                return tmp;
            }

        }
    }
}

Necromancing. Necromancing。
For those still on .NET 2.0 对于仍然使用.NET 2.0的用户
It is in fact quite easy, if you know how. 事实上,如果你知道如何,这很容易。

Problem is, you can't set the host header, because the framework won't let you change the value at runtime. 问题是,你不能设置主机头,因为框架不会让你在运行时更改值。 (.net framework 4.0+ will let you override host in a httpwebrequest). (.net framework 4.0+将允许您覆盖httpwebrequest中的主机)。

Next attempt will be setting the header with reflection, to get around it, which will let you change the header value. 下一次尝试将使用反射设置标题,以绕过它,这将允许您更改标题值。 But at runtime, it will overwrite this value with the host part of the url, which means reflection will bring you nothing. 但是在运行时,它将使用url的主机部分覆盖此值,这意味着反射将不会带来任何结果。

If the dns-name doesn't exist, which is quite frankly the only case in which you want to do this in the first place, you can't set it, because .NET can't resolve it, and you can't override the .NET DNS resolver. 如果dns-name不存在,坦率地说,这是你想要在第一时间执行此操作的唯一情况,你无法设置它,因为.NET无法解决它,你不能覆盖.NET DNS解析器。

But what you can do, is setting a webproxy with the exact same IP as the destination server. 但是你可以做的是设置一个webproxy与目标服务器完全相同的IP。

So, if your server IP is 28.14.88.71: 因此,如果您的服务器IP是28.14.88.71:

public class myweb : System.Net.WebClient
{
    protected override System.Net.WebRequest GetWebRequest(System.Uri address)
    {
        System.Net.WebRequest request = (System.Net.WebRequest)base.GetWebRequest(address);
        //string host = "redmine.nonexistantdomain.com";

        //request.Headers.GetType().InvokeMember("ChangeInternal",
        //    System.Reflection.BindingFlags.NonPublic |
        //    System.Reflection.BindingFlags.Instance |
        //    System.Reflection.BindingFlags.InvokeMethod, null,
        //    request.Headers, new object[] { "Host", host }
        //);

        //server IP and port
        request.Proxy = new System.Net.WebProxy("http://28.14.88.71:80");

        // .NET 4.0 only
        System.Net.HttpWebRequest foo = (System.Net.HttpWebRequest)request;
        //foo.Host = host;

        // The below reflection-based operation is not necessary, 
        // if the server speaks HTTP 1.1 correctly
        // and the firewall doesn't interfere
        // https://yoursunny.com/t/2009/HttpWebRequest-IP/
        System.Reflection.FieldInfo horribleProxyServicePoint = (typeof(System.Net.ServicePoint))
            .GetField("m_ProxyServicePoint", System.Reflection.BindingFlags.NonPublic |
            System.Reflection.BindingFlags.Instance);

        horribleProxyServicePoint.SetValue(foo.ServicePoint, false);
        return foo;



        return request;
    }


    }

and voila, now 瞧,现在

myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.non-existant-domain.com");

and you get the correct page back, if 28.14.88.71 is a webserver with virtual name-based hosting (based on http-host-header). 如果28.14.88.71是具有基于虚拟名称的托管的Web服务器(基于http-host-header),则会得到正确的页面。

WebClient allows it. WebClient允许它。

var client = new WebClient();
client.Headers.Add( "Host", WebHeader );

I couldn't tell you why. 我不知道为什么。 The documentation clearly states that Host is a system header. 文档明确指出Host是系统头。

你可以使用代理,请参阅我的答案: 在c#欺骗主机中请求网页

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

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