如何在 HttpWebRequest 中设置自定义 Host 标头?我知道通常这个类不允许你这样做,但是无论如何使用反射或类似的东西而不需要我用 TCPClient 发送整个数据包?
5 回答
有一种迂回的方法可以做到这一点,如下所述:
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
希望这可以帮助。
死灵术。
对于那些仍在使用 .NET 2.0的人
来说,如果您知道如何操作,这实际上很容易。
问题是,您不能设置主机标头,因为框架不允许您在运行时更改值。(.net framework 4.0+ 将允许您在 httpwebrequest 中覆盖主机)。
下一次尝试将设置带有反射的标题,以绕过它,这将让您更改标题值。但是在运行时,它会用 url 的 host 部分覆盖这个值,这意味着反射不会给你带来任何东西。
如果 dns-name 不存在,坦率地说,这是您首先要执行此操作的唯一情况,您无法设置它,因为 .NET 无法解析它,而且您也无法覆盖 .NET DNS 解析器。
但是您可以做的是设置一个与目标服务器具有完全相同 IP 的网络代理。
所以,如果你的服务器 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)的网络服务器,那么您会得到正确的页面。
您可以使用这个 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;
}
}
}
}
WebClient 允许它。
var client = new WebClient();
client.Headers.Add( "Host", WebHeader );
我不能告诉你为什么。文档明确指出 Host 是系统标头。
您可以使用代理,请参阅我的回答: Request Web Page in c# spoofing the Host