【发布时间】:2011-11-27 01:23:23
【问题描述】:
我正在尝试以编程方式下载从网站上的用户输入(HTML 表单)生成的文件。该网站要求用户登录。
我研究了网站如何使用 Tamper Data Firefox 插件工作,这基本上就是在 Firefox 中手动下载时发生的情况:
- 我转到该网站的主页
- 我输入我的凭据并点击“登录”
- 这会触发对 URL A 的 POST 请求并设置“IdSes”(我猜是会话 ID)cookie(以及其他)
- 我转到让我下载文件的页面
- 我输入了一些东西(文件格式等)
- 我点击“下载”
- 这会触发对 URL B(一个 ASP 页面)的 POST 请求。响应代码为 200 并包含文件。
通过篡改对 URL B 的 POST 请求,我确保了 IdSes cookie 是请求成功所需的唯一一个。如果 IdSes 值不正确或不存在,则响应代码为 302,并且我被重定向到 URL A,并且我似乎仍在登录(显示我的姓名)。如果我在 POST 数据(最初来自表单)中放入垃圾,我会进入正确的 ASP 页面,但会显示错误。
现在我尝试使用 C# 进行下载,而不做我认为不必要的事情(即所有 GET):
// URL A is loginUrl, URL B is retrieveUrl
public void RetrieveFile(
string loginUrl, IDictionary<string, string> loginData,
string retrieveUrl, IDictionary<string, string> retrieveData) {
var cookies = new CookieContainer();
var loginRequest = CreatePostRequest(loginUrl, loginData);
loginRequest.CookieContainer = cookies;
var loginResponse = loginRequest.GetResponse();
loginResponse.Close();
var retrieveRequest = CreatePostRequest(retrieveUrl, retrieveData);
retrieveRequest.CookieContainer = cookies;
var response = retrieveRequest.GetResponse();
using (
Stream responseStream = response.GetResponseStream(),
outputFile = new FileStream("response.html", FileMode.Create)) {
responseStream.CopyTo(outputFile);
}
}
private HttpWebRequest CreatePostRequest(string url, IDictionary<string, string> data) {
var request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var postData = EncodePostData(data);
request.ContentLength = postData.Length;
return request;
}
private byte[] EncodePostData(IDictionary<string, string> data) {
var dataAsStrings =
from entry in data
select String.Format("{0}={1}", entry.Key, entry.Value);
var dataAsString = String.Join("&", dataAsStrings);
// Encode in Latin-1 / ISO 8859-1
var dataAsBytes = Encoding.GetEncoding(1252).GetBytes(dataAsString);
return dataAsBytes;
}
发生的情况是“response.html”包含位于 URL A 的页面,就像 IdSes cookie 的值错误或不存在一样。但是,如果我在loginRequest.GetResponse() 之后打印cookies 中存在的所有cookie,则存在IdSes。我做错了吗?
【问题讨论】:
-
可能不正确,但为什么不尝试在第一次调用
GetResponse后关闭响应?如果我不这样做,我已经看到不守规矩的事情发生了,出于某种原因,这可能是相关的。不过我可能错了。 -
哦,我不知道如果我不使用它的流,我必须关闭它。然而它并没有解决问题。我将编辑我的代码以反映更改。感谢您指出这一点。
-
因为是 POST 请求,我想知道网站是否验证 REFERER 标头,如果不在同一个域(或为空!),则基本上不会将您的请求视为有效,导致您看到的行为。现在,只要它是一个 GET 请求,你就会很成功。
标签: c# httprequest