Cookie HttpWebReponse Tidak Disetel Untuk Pengalihan

Saya mencoba melakukan hal berikut:

  1. kirim permintaan GET untuk mengambil halaman login (yang meminta nama pengguna, kata sandi, dan menyetel cookie)
  2. buat permintaan POST yang mengirimkan cookie dari #1 dan isi nama pengguna/kata sandi (ini mengembalikan Set-Cookie dan mengalihkan ke halaman arahan situs web untuk pengguna yang masuk)

Masalah saya adalah dengan pengalihan 302. Server web mengembalikan 302 dengan Set-Cookie, tetapi ketika HttpWebRequests dialihkan secara otomatis, ia tidak meneruskan cookie yang sekarang diperbarui. Untuk menyiasatinya, saya mencoba menyetel .AllowAutoRedirect = false, menyimpan cookie di CookieCollection, lalu membuat permintaan HTTP ke-3: GET ke lokasi 302 terakhir. Sayangnya, saya tidak dapat menyetel cookie pada permintaan ini. Saya tidak yakin mengapa dan itu membuat saya gila.

Permintaan HTTP, secara berurutan, diberi nama 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();

Di redirectRequest.CookieContainer.Add(cookies);, objek cookies berisi cookie yang benar. Namun ketika saya melihat dengan Fiddler, saya hanya melihat info ini:

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

Aku seperti membenturkan kepalaku ke dinding saat ini. Ada saran? Apakah saya merujuk sesuatu yang salah? Hati-hati, saya biasanya tidak menulis kode C#


person tommy_o    schedule 13.02.2014    source sumber


Jawaban (1)


Saya tidak dapat menyelesaikan masalah ini sendiri, tetapi menemukan cuplikan kode yang berguna dari entri blog ini oleh @malte-clasen. Kode ada di Github dan saya telah melampirkannya di sini untuk retensi.

Saya menghapus komponen async karena itu tidak diperlukan dalam kode saya.

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 menyelesaikan masalah saya.

person tommy_o    schedule 14.02.2014
comment
Saya juga berada dalam situasi yang sama seperti tommy_o. Tapi aplikasi yang saya kerjakan, kami menggunakan .NET 4.0. Bantuan atau bimbingan apa pun sangat dihargai. - person Aishu; 26.07.2015