2014-02-13 61 views
2

我試圖做到以下幾點:HttpWebReponse Cookie不能設置爲重定向

  1. 發送GET請求來獲取一個登錄頁面(即提示提供用戶名,密碼,並設置一個cookie)
  2. 構建一個POST請求,從#1發送cookie和一個用戶名/密碼的主體(這將返回一個Set-Cookie並重定向到登錄用戶的網站着陸頁)

我的麻煩是302重定向。網絡服務器返回302與Set-Cookie,但是當HttpWebRequests自動重定向時,它不會傳遞現在更新的cookie。爲了解決這個問題,我試圖設置.AllowAutoRedirect = false,將Cookie保存在CookieCollection中,然後構建第三個HTTP請求:GET到最終的302位置。很遺憾,我無法根據此請求設置Cookie。我不知道爲什麼,這讓我發瘋。

HTTP請求按順序命名爲request,postRequest,redirectRequest。

string loginGetUrl = "https://<..>/signin.htm"; 
string loginPostUrl = "https://<..>/j_acegi_security_check"; 
string loginRedirectUrl = "https://<..>/centraladmin/poslinks.htm"; 

string postData = String.Format("j_username={0}&j_password={1}", username, password); 

CookieCollection cookies = new CookieCollection(); 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(loginGetUrl); 
request.CookieContainer = new CookieContainer(); 
request.CookieContainer.Add(cookies); 
//Get the response from the server and save the cookies from the first request.. 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
cookies = response.Cookies;   

HttpWebRequest postRequest = (HttpWebRequest)WebRequest.Create(loginPostUrl); 
postRequest.CookieContainer = new CookieContainer(); 

// Add the received Cookies from the HTTP Get 
postRequest.CookieContainer.Add(cookies); 
postRequest.Method = WebRequestMethods.Http.Post; 
postRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2"; 
postRequest.AllowWriteStreamBuffering = false; 
postRequest.ProtocolVersion = HttpVersion.Version11; 
postRequest.AllowAutoRedirect = false; 
postRequest.ContentType = "application/x-www-form-urlencoded"; 

byte[] byteArray = Encoding.ASCII.GetBytes(postData); 
postRequest.ContentLength = byteArray.Length; 
Stream newStream = postRequest.GetRequestStream(); //open connection 
newStream.Write(byteArray, 0, byteArray.Length); // Send the data. 
newStream.Close(); 

HttpWebResponse postResponse = (HttpWebResponse)postRequest.GetResponse(); 

// Save the cookies from the POST login request, then send them on to the redirected URL 
cookies = postResponse.Cookies; 

HttpWebRequest redirectRequest = (HttpWebRequest)WebRequest.Create(loginRedirectUrl); 
redirectRequest.CookieContainer = new CookieContainer(); 

// add cookies from POST 
redirectRequest.CookieContainer.Add(cookies); 
HttpWebResponse redirectResponse = (HttpWebResponse)redirectRequest.GetResponse(); 

redirectRequest.CookieContainer.Add(cookies);,cookie對象包含正確的cookie。但是當我和小提琴手一起看時,我只看到這個信息:

GET https://<...>/centraladmin/poslinks.htm HTTP/1.1 
Host: host:port 

我有點在牆上敲打我的頭。有什麼建議麼?我指的是錯誤的嗎?請注意,我通常不會編寫C#代碼

回答

1

我無法自行解決這個問題,但可以從@ malte-clasen找到this blog post的有用代碼段。代碼位於Github,我已將其附加在此保留。

我刪除了異步組件,因爲它在我的代碼中不是必需的。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Threading.Tasks; 

namespace DracWake.Core 
{ 
    public class WebClient : IWebClient 
    { 
     private readonly CookieContainer _cookies = new CookieContainer(); 

     private HttpWebRequest CreateRequest(Uri uri) 
     { 
      var request = HttpWebRequest.CreateHttp(uri); 
      request.AllowAutoRedirect = false; 
      request.CookieContainer = _cookies; 
      SetHeaders(request); 
      var defaultValidator = System.Net.ServicePointManager.ServerCertificateValidationCallback; 
      request.ServerCertificateValidationCallback = 
       (sender, certificate, chain, sslPolicyErrors) => 
        certificate.Subject.Contains("O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com") 
        || (certificate.Subject == "CN=DRAC5 default certificate, OU=Remote Access Group, O=Dell Inc., L=Round Rock, S=Texas, C=US") 
        || (defaultValidator != null && defaultValidator(request, certificate, chain, sslPolicyErrors)); 
      return request; 
     } 

     private async Task<string> DecodeResponse(HttpWebResponse response) 
     { 
      foreach (System.Net.Cookie cookie in response.Cookies) 
      { 
       _cookies.Add(new Uri(response.ResponseUri.GetLeftPart(UriPartial.Authority)), cookie); 
      } 

      if (response.StatusCode == HttpStatusCode.Redirect) 
      { 
       var location = response.Headers[HttpResponseHeader.Location]; 
       if (!string.IsNullOrEmpty(location)) 
        return await Get(new Uri(location)); 
      } 

      var stream = response.GetResponseStream(); 
      var buffer = new System.IO.MemoryStream(); 
      var block = new byte[65536]; 
      var blockLength = 0; 
      do{ 
       blockLength = stream.Read(block, 0, block.Length); 
       buffer.Write(block, 0, blockLength); 
      } 
      while(blockLength == block.Length); 

      return Encoding.UTF8.GetString(buffer.GetBuffer()); 
     } 

     public async Task<string> Get(Uri uri) 
     { 
      var request = CreateRequest(uri); 
      var response = (HttpWebResponse) await request.GetResponseAsync(); 
      return await DecodeResponse(response); 
     } 

     private void SetHeaders(HttpWebRequest request) 
     { 
      request.Accept = "text/html, application/xhtml+xml, */*"; 
      request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; 
      request.ContentType = "application/x-www-form-urlencoded"; 
      request.Headers[HttpRequestHeader.AcceptLanguage] = "en-US,en;q=0.8,de-DE;q=0.5,de;q=0.3"; 
      request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate"; 
      request.Headers[HttpRequestHeader.CacheControl] = "no-cache"; 
     } 

     public async Task<string> Post(Uri uri, byte[] data) 
     { 
      var request = CreateRequest(uri); 
      request.Method = "POST"; 
      request.GetRequestStream().Write(data, 0, data.Length); 
      var response = (HttpWebResponse) await request.GetResponseAsync(); 
      return await DecodeResponse(response); 
     } 
    } 
} 

DecodeResponse解決了我的問題。

+0

我也處於類似的情況,像tommy_o。但是我正在使用的應用程序,我們使用.NET 4.0。任何幫助或指導,非常感謝。 – Aishu

相關問題