คุกกี้ HttpWebReponse ไม่ได้ตั้งค่าสำหรับการเปลี่ยนเส้นทาง

ฉันกำลังพยายามทำสิ่งต่อไปนี้:

  1. ส่งคำขอ GET เพื่อดึงข้อมูลหน้าเข้าสู่ระบบ (ซึ่งจะแจ้งชื่อผู้ใช้ รหัสผ่าน และตั้งค่าคุกกี้)
  2. สร้างคำขอ POST ที่ส่งคุกกี้จาก #1 และเนื้อหาของชื่อผู้ใช้/รหัสผ่าน (ซึ่งจะส่งคืน Set-Cookie และเปลี่ยนเส้นทางไปยังหน้า Landing Page ของเว็บไซต์สำหรับผู้ใช้ที่เข้าสู่ระบบ)

ปัญหาของฉันอยู่ที่การเปลี่ยนเส้นทาง 302 เว็บเซิร์ฟเวอร์ส่งคืน 302 ด้วย Set-Cookie แต่เมื่อ HttpWebRequests เปลี่ยนเส้นทางอัตโนมัติ จะไม่ส่งผ่านคุกกี้ที่อัปเดตในขณะนี้ เพื่อหลีกเลี่ยงปัญหาดังกล่าว ฉันกำลังพยายามตั้งค่า .AllowAutoRedirect = false บันทึกคุกกี้ใน CookieCollection จากนั้นสร้างคำขอ HTTP ลำดับที่ 3: GET ไปยังตำแหน่ง 302 สุดท้าย ขออภัย ฉันไม่สามารถตั้งค่าคุกกี้ตามคำขอนี้ได้ ฉันไม่แน่ใจว่าทำไม และมันทำให้ฉันเป็นบ้า

คำขอ HTTP ตามลำดับ คำขอที่มีชื่อ postRequest, เปลี่ยนเส้นทางคำขอ

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); วัตถุคุกกี้ประกอบด้วยคุกกี้ที่ถูกต้อง แต่เมื่อฉันดูด้วย Fiddler ฉันเห็นเพียงข้อมูลนี้:

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

ตอนนี้ฉันกำลังเอาหัวโขกกำแพงอยู่ มีข้อเสนอแนะอะไรบ้าง? ฉันกำลังอ้างอิงถึงสิ่งผิดหรือเปล่า? ระวัง ปกติฉันจะไม่เขียนโค้ด C#


person tommy_o    schedule 13.02.2014    source แหล่งที่มา


คำตอบ (1)


ฉันไม่สามารถแก้ไขปัญหานี้ด้วยตนเองได้ แต่พบข้อมูลโค้ดที่เป็นประโยชน์จาก โพสต์ในบล็อกนี้ โดย @malte-clasen รหัสอยู่บน Github และฉันได้แนบมาด้วย ที่นี่เพื่อการเก็บรักษา

ฉันลบส่วนประกอบ async ออกเนื่องจากไม่จำเป็นในโค้ดของฉัน

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 แก้ไขปัญหาของฉันแล้ว

person tommy_o    schedule 14.02.2014
comment
ฉันก็อยู่ในสถานการณ์ที่คล้ายกันเช่น tommy_o แต่แอปที่ฉันกำลังทำอยู่ เราใช้ .NET 4.0 ความช่วยเหลือหรือคำแนะนำใด ๆ ที่ชื่นชมอย่างมาก - person Aishu; 26.07.2015