我正在尝试以编程方式下载从网站上的用户输入(HTML表单)生成的文件。该网站要求用户登录。
我已经研究了网站如何使用Tamper Data Firefox插件工作,这基本上是在Firefox中手动下载时发生的事情:
通过篡改POST请求到URL B,我确保IdSes cookie是请求成功所需的唯一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的值不正确或缺席一样。但是,如果我在cookies
之后打印loginRequest.GetResponse()
中存在的所有Cookie,则会显示IdSes。我做错了吗?
答案 0 :(得分:1)
因为这是一个POST请求,所以我想知道网站是否验证HTTP_REFERER
标头,并且如果不在同一个域(或为空!)上,则基本上不会将您的请求视为有效,因此在您看到的行为上。
您可以尝试在检索请求中欺骗HTTP_REFERER标头,然后看看会发生什么。
retrieveRequest.Referer = "http://www.originatingdomain.com";
答案 1 :(得分:0)
这看起来并不像您将最初从loginRequest检索到的cookie传递给retrieveRequest处理程序。
更改
retrieveRequest.CookieContainer = cookies;
到
retrieveRequest.CookieContainer = loginRequest.CookieContainer;
看看会发生什么。