body - webresponse c#




請求c#中的網頁欺騙主機 (6)

我需要創建一個網頁的請求傳遞到我們的網站,但我需要能夠設置主機頭信息。 我已經試過這個使用HttpWebRequest,但頭信息是只讀的(或至少是主機的一部分)。 我需要這樣做,因為我們想在用戶可以之前執行頁面的初始請求。 我們有10個負載均衡的Web服務器,所以我們需要從每個Web服務器請求文件。

我已經嘗試了以下內容:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://192.168.1.5/filename.htm");
request.Headers.Set("Host", "www.mywebsite.com");
WebResponse response = request.GetResponse();

顯然這是行不通的,因為我不能更新標題,我不知道這是否是正確的方法。


“主機”標題受保護,不能以編程方式修改。 我想解決這個問題,你可以嘗試通過反射綁定WebRequest對象的私有“InnerCollection”屬性,並調用“Set”和“Add”方法來修改Host頭。 我沒有嘗試過,但是從Reflector中的源代碼快速查看,我認為它很容易完成。 但是,綁定框架對象的私有屬性並不是完成任務的最佳方式。 :)只有當你必須使用。

編輯:或者像其他人提到的鏈接問題,只需打開一個套接字,並手動執行一個快速的“GET”。 如果你不需要修改其他的東西,比如cookies或者其他的HttpWebRequest所提供的細節,那麼應該不用理會。


我已經設法找出一個更長的蜿蜒的路線使用套接字。 我在IPEndPoint的MSDN頁面找到了答案:

string getString = "GET /path/mypage.htm HTTP/1.1\r\nHost: www.mysite.mobi\r\nConnection: Close\r\n\r\n";
Encoding ASCII = Encoding.ASCII;
Byte[] byteGetString = ASCII.GetBytes(getString);
Byte[] receiveByte = new Byte[256];
Socket socket = null;
String strPage = null;
try
{
    IPEndPoint ip = new IPEndPoint(IPAddress.Parse("10.23.1.93"), 80);
    socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(ip);
}
catch (SocketException ex)
{
    Console.WriteLine("Source:" + ex.Source);
    Console.WriteLine("Message:" + ex.Message);
}
socket.Send(byteGetString, byteGetString.Length, 0);
Int32 bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
strPage = strPage + ASCII.GetString(receiveByte, 0, bytes);

while (bytes > 0)
{
    bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
    strPage = strPage + ASCII.GetString(receiveByte, 0, bytes);
}
socket.Close();


我有一個問題,我使用的URL有多個不同的IP地址,我想單獨使用主機中相同的DNS名稱來調用每個地址 - 解決方案是使用代理:

string retVal = "";
            // Can't change the 'Host' header property because .NET protects it
            // HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            // request.Headers.Set(HttpRequestHeader.Host, DEPLOYER_HOST);
            // so we must use a workaround
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Proxy = new WebProxy(ip);
            using (WebResponse response = request.GetResponse())
            {
                using (TextReader reader = new StreamReader(response.GetResponseStream()))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                        retVal += line;
                }
            }
            return retVal;

主機頭由.NET自動設置為'url','ip'包含你要聯繫的Web服務器的實際地址(你也可以在這裡使用一個dns名字)


我知道這是一個古老的問題,但這些日子,你可以做。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://192.168.1.5/filename.htm");
request.Host = "www.mywebstite.com";
WebResponse response = request.GetResponse();

Necromancing。
對於那些仍然在.NET 2.0上
事實上,如果你知道如何,這實際上很簡單。

問題是,你不能設置主機頭,因為框架不會讓你在運行時改變值。 (.net framework 4.0+會讓你重載httpwebrequest中的主機)。

接下來的嘗試將是用反射來設置標題 - 就像這裡最高的答案所示 - 解決它,這將允許你改變標題的值。 但是在運行時,它會用url的主機部分覆蓋這個值,這意味著反射會給你帶來什麼,這就是為什麼我明白為什麼人們繼續投票。

如果dns-name不存在,這是坦率地說你想要做的唯一的情況,你不能設置它,因為.NET不能解決它,你不能重寫.NET DNS解析器。

但是你可以做的是設置一個與目標服務器完全相同的IP地址的webproxy。

所以,如果你的服務器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; // or return request; if you don't neet this
    }


    }

現在瞧

myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.netexistantdomain.com");

並且如果28.14.88.71是一個具有基於虛擬名稱的託管(基於http-host-header)的網絡服務器,則會返回正確的頁面。

現在,您對WebRequest和WebClient的原始問題都有了正確的答案。 我認為使用自定義套接字來做到這一點將是錯誤的方法,特別是當應該使用SSL,並且當一個實際的解決方案是那麼簡單...





http-headers