Đăng nhập vào trang web, qua C #


81

Tôi tương đối mới sử dụng C # và có một ứng dụng đọc các phần của mã nguồn trên một trang web. Đó là tất cả các hoạt động; nhưng vấn đề là trang được đề cập yêu cầu người dùng đăng nhập để truy cập mã nguồn này. Chương trình của tôi cần một cách để đăng nhập ban đầu người dùng vào trang web- sau khi hoàn tất, tôi sẽ có thể truy cập và đọc mã nguồn.

Trang web cần đăng nhập là: mmoinn.com/index.do?PageModule=UsersLogin

Tôi đã tìm kiếm cả ngày về cách làm điều này và thử các ví dụ, nhưng không gặp may.

Cảm ơn trước


Vì vậy, tôi có thể nghĩ ra rất nhiều cách để thực hiện việc này ... Chương trình C # có yêu cầu 'mã' trực tiếp từ máy chủ thông qua HTTP hay bạn đặt cọc trên ứng dụng trình duyệt hay sao? Một chút thông tin là cần thiết.
Mitch Baker

Chương trình sử dụng WebClient.DownloadString ("URL")

Câu trả lời:


112

Bạn có thể tiếp tục sử dụng WebClient để ĐĂNG (thay vì GET, là động từ HTTP bạn hiện đang sử dụng với DownloadString), nhưng tôi nghĩ bạn sẽ thấy dễ dàng hơn khi làm việc với các lớp cấp thấp hơn (một chút) là WebRequest và WebResponse.

Điều này có hai phần - đầu tiên là đăng biểu mẫu đăng nhập, thứ hai là khôi phục tiêu đề "Set-cookie" và gửi tiêu đề đó trở lại máy chủ dưới dạng "Cookie" cùng với yêu cầu GET của bạn. Máy chủ sẽ sử dụng cookie này để nhận dạng bạn kể từ bây giờ (giả sử nó đang sử dụng xác thực dựa trên cookie mà tôi khá tin tưởng vì trang đó trả về tiêu đề Set-cookie bao gồm "PHPSESSID").


ĐĂNG lên biểu mẫu đăng nhập

Các bài đăng trên biểu mẫu rất dễ mô phỏng, đó chỉ là một trường hợp định dạng dữ liệu bài đăng của bạn như sau:

field1=value1&field2=value2

Sử dụng WebRequest và mã mà tôi đã điều chỉnh từ Scott Hanselman , đây là cách bạn ĐĂNG dữ liệu biểu mẫu lên biểu mẫu đăng nhập của mình:

string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin"; // NOTE: This is the URL the form POSTs to, not the URL of the form (you can find this in the "action" attribute of the HTML's form tag
string formParams = string.Format("email_address={0}&password={1}", "your email", "your password");
string cookieHeader;
WebRequest req = WebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
    os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];

Đây là một ví dụ về những gì bạn sẽ thấy trong tiêu đề Set-cookie cho biểu mẫu đăng nhập của bạn:

PHPSESSID=c4812cffcf2c45e0357a5a93c137642e; path=/; domain=.mmoinn.com,wowmine_referer=directenter; path=/; domain=.mmoinn.com,lang=en; path=/;domain=.mmoinn.com,adt_usertype=other,adt_host=-

Lấy trang phía sau biểu mẫu đăng nhập

Bây giờ bạn có thể thực hiện yêu cầu GET của mình đến một trang mà bạn cần đăng nhập.

string pageSource;
string getUrl = "the url of the page behind the login";
WebRequest getRequest = WebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
WebResponse getResponse = getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

BIÊN TẬP:

Nếu bạn cần xem kết quả của BÀI ĐĂNG đầu tiên, bạn có thể khôi phục HTML mà nó trả về bằng:

using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

Đặt cái này ngay bên dưới cookieHeader = resp.Headers["Set-cookie"];và sau đó kiểm tra chuỗi được giữ trong pageSource.


Cảm ơn rất nhiều cho câu trả lời chi tiết; nhưng vẫn còn một phần mà tôi không chắc chắn. Tôi có phải đang thay đổi điều gì đó liên quan đến "Set -cookie", "Cookie" hoặc "PHPSESSID" mà bạn đã đăng không? Tôi đã thử đơn giản bằng cách sử dụng mã đó trong một chương trình có nhập thông tin của tôi, nhưng có vẻ như nó không đăng nhập được cho tôi (tôi cho rằng tôi đang gặp rắc rối với cookie).

Mã phải được sử dụng nguyên văn. Máy chủ đặt cookie (trong Set-cookie) và máy khách (chính là bạn) gửi cookie sao lưu dưới dạng Cookie). Điều đầu tiên cần kiểm tra là POST đầu tiên thực sự đăng nhập cho bạn, bạn có thể thấy máy chủ mong đợi một trường khác trong biểu mẫu POST của bạn (nghe thật lạ, đôi khi bạn cần một trường trống có tên của nút). Tôi đã cập nhật bài đăng để hướng dẫn cách xem kết quả của BÀI ĐĂNG.
Matt Brindley,

Tôi không chắc mình đã làm gì sai trong lần đầu tiên, nhưng nó đã hoạt động ngay bây giờ! Cảm ơn rất nhiều cho sự giúp đỡ.

1
Làm cách nào để xác định xem người dùng đã xác thực thành công hay chưa?
Cyral

2
Tôi biết chúng ta không nên cảm ơn ở đây nhưng anh bạn đã cứu tôi! +1
Owen James

39

Bạn có thể đơn giản hóa mọi thứ một chút bằng cách tạo một lớp có nguồn gốc từ WebClient, ghi đè phương thức GetWebRequest của nó và đặt đối tượng CookieContainer trên đó. Nếu bạn luôn đặt cùng một phiên bản CookieContainer, thì việc quản lý cookie sẽ được xử lý tự động cho bạn.

Nhưng cách duy nhất để truy cập HttpWebRequest trước khi nó được gửi đi là kế thừa từ WebClient và ghi đè phương thức đó.

public class CookieAwareWebClient : WebClient
{
    private CookieContainer cookie = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = cookie;
        }
        return request;
    }
}

var client = new CookieAwareWebClient();
client.BaseAddress = @"https://www.site.com/any/base/url/";
var loginData = new NameValueCollection();
loginData.Add("login", "YourLogin");
loginData.Add("password", "YourPassword");
client.UploadValues("login.php", "POST", loginData);

//Now you are logged in and can request pages    
string htmlSource = client.DownloadString("index.php");

Khi gỡ lỗi, cookie (đặt nó ở chế độ công khai) luôn trống. Trang web chắc chắn cung cấp cookie trên các trang tôi đang tải xuống.
C4d

Cảm ơn, sau nhiều giờ phục vụ tìm giải pháp, điều này đã hoạt động!
Essej

9

Matthew Brindley , mã của bạn hoạt động rất tốt cho một số trang web mà tôi cần (có đăng nhập), nhưng tôi cần phải thay đổi thành HttpWebRequestHttpWebResponsenếu không, tôi nhận được Yêu cầu 404 Xấu từ máy chủ từ xa. Ngoài ra tôi muốn chia sẻ cách giải quyết của tôi sử dụng mã của bạn, và là tôi đã thử nó để đăng nhập vào một trang web dựa trên moodle , nhưng nó đã không làm việc ở bước bạn " Bắt trang đằng sau biểu mẫu đăng nhập " bởi vì khi thành công gửi bài các đăng nhập, Header 'Set-Cookie'không trả lại bất cứ điều gì mặc dù các trang web khác có.

Vì vậy, tôi nghĩ rằng đây là nơi chúng tôi cần lưu trữ cookie cho các Yêu cầu tiếp theo, vì vậy tôi đã thêm điều này.


Đối với khối mã " ĐĂNG lên biểu mẫu đăng nhập ":

var cookies = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookies;


Và đến " Lấy trang đằng sau biểu mẫu đăng nhập ":

HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
getRequest.CookieContainer = new CookieContainer();
getRequest.CookieContainer.Add(resp.Cookies);
getRequest.Headers.Add("Cookie", cookieHeader);


Thực hiện việc này, hãy cho phép tôi Đăng nhập và lấy mã nguồn của "trang sau khi đăng nhập" (trang web dựa trên tâm trạng) Tôi biết đây là cách sử dụng mơ hồ của CookieContainervà HTTPCookies bởi vì trước tiên chúng tôi có thể hỏi xem trước đó đã lưu bộ cookie nào chưa gửi yêu cầu đến máy chủ. Cách này vẫn hoạt động mà không có vấn đề gì, nhưng đây là một thông tin tốt để đọc WebRequestWebResponsevới các dự án mẫu và hướng dẫn:
Truy xuất nội dung HTTP trong .NET
Cách sử dụng HttpWebRequest và HttpWebResponse trong .NET


2

Đôi khi, nó có thể giúp tắt AllowAutoRedirectvà đặt cả yêu cầu đăng nhập POSTvà trang GETcho cùng một tác nhân người dùng.

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.