.net 如何在HttpWebRequest中设置自定义的“Host”头?

b5lpy0ml  于 2022-11-19  发布在  .NET
关注(0)|答案(5)|浏览(408)

如何在HttpWebRequest中设置一个自定义的主机头?我知道通常这个类不允许这样做,但是有没有办法使用反射或类似的东西,而不需要我用TCPClient发送整个数据包?

axzmvihb

axzmvihb1#

有一种迂回的方法可以做到这一点,如下所述:
http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx
但是,框架的下一个版本(.NET Framework 4.0)将使这一点变得更容易。
http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
希望这对你有帮助。

fquxozlt

fquxozlt2#

招魂术。
对于仍在使用.NET 2.0的用户
如果你知道怎么做的话,这实际上是很容易的。
问题是,你不能设置主机头,因为框架不允许你在运行时更改值。(.net framework 4.0+允许你在httpwebrequest中重写主机)。
下一个尝试是用反射来设置header,这样你就可以改变header的值,但是在运行时,它会用url的主机部分覆盖这个值,这意味着反射不会给你带来任何东西。
如果dns-name不存在(坦率地说,这是您首先要执行此操作的唯一情况),则无法设置它,因为.NET无法解析它,并且您无法覆盖.NET DNS解析器。
但你可以做的是设置一个与目标服务器IP完全相同的Web代理。
因此,如果您的服务器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;
    }

    }

瞧现在

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

并且如果28.14.88.71是一个基于虚拟名称的主机(基于http-host-header)的Web服务器,则返回正确的页面。

iezvtpos

iezvtpos3#

你可以使用这个黑客,专为解决这个问题在.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);

            ClusteredHeaderCollection headers = new ClusteredHeaderCollection("stackoverflow.com");

            headersFieldInfo.SetValue(request, headers);

            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 ClusteredHeaderCollection : WebHeaderCollection
        {
            public bool HostHeaderValueReplaced { get;private  set; }

            public string ClusterUrl { get; private set; }

            public ClusteredHeaderCollection(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;
            }
        }
    }
}
xzv2uavs

xzv2uavs4#

WebClient允许这样做。

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

我不能告诉你为什么。文档清楚地说明主机是一个系统头文件。

e7arh2l6

e7arh2l65#

您可以使用代理,请参阅我答复:在C#中请求网页欺骗主机

相关问题