对于它的价值,我设法让一个控制台应用程序通过现有的 ASP.NET Web 应用程序对自己进行身份验证。它只是通过向包含视图状态信息的登录页面发出发布请求来模拟登录页面(就像浏览器发出请求一样)。
然后它会在 CookieContainer 中捕获作为响应返回的 cookie。
然后应用程序继续向同一页面发出多个请求(这需要授权)。该页面做了一些工作并在服务器上写出一个文件。
我遇到的问题是,在假登录后,前两个请求可以通过。第三个请求甚至从未收到响应。下面是我用来发出请求的代码:
登录:
private static CookieContainer PerformLoginRequest()
{
string loginURL = "http://www.myDomain.com/mySite/login.aspx";
//Set up the request and give it a cookie container.
CookieContainer cookieJar = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(loginURL);
request.CookieContainer = cookieJar;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//Grab the request body so we can put important information in it.
Stream requestBody = request.GetRequestStream();
string postData = "__VIEWSTATE=GIBBERISH&UserName=USERNAME&Password=PASSWORD%21&LoginButton.x=0&LoginButton.y=0";
//Throw the string into the body.
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData);
requestBody.Write(byte1, 0, byte1.Length);
requestBody.Close();
//Get the response to the login request.
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
reader.Close();
return cookieJar;
}
请求页面:
private static long RequestPage(string url)
{
//If we've already got a CookieContainer, then we've logged in already. Otherwise, log in.
if (cookieJar == null)
{
try
{
cookieJar = PerformLoginRequest();
}
catch
{
throw;
}
}
//Set up the request.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.CookieContainer = cookieJar;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = timeout; //5 minutes.
WebResponse response = request.GetResponse();
return response.ContentLength;
}
cookieJar 和 timeout 变量对于应用程序是全局的。
知道什么会导致这种情况吗?
更新(2010-01-17,美国东部标准时间下午 3:30)
当我在 Fiddler 运行的情况下启动应用程序时,一切正常。正如我所期望的那样,所有请求都起作用。
我检查了 IIS 日志文件。在它们中,我可以看到初始登录请求、登录后的重定向以及前两页的请求。但在那之后……什么都没有。就好像请求甚至没有发送到 Web 服务器。
更新(2010-01-18,美国东部标准时间上午 11:29)
我更新了代码以反映 Chris B. Behrens 建议的更改。但无济于事。如果重要的话,调用上述函数的循环如下所示:
private static void RegenerateNecessaryForms(MyEntities context)
{
var items = context.Items.Where(i => i.NeedsProcessing == true);
var area = context.Areas;
foreach (Item i in items)
{
bool success = true;
foreach (Area area in areas)
{
try
{
string url = string.Format("http://{0}/mySite/process.aspx?item={1}&area={2}", targetDomain, i.ItemName, area.AreaName);
long result = RequestPage(url, m);
}
catch
{
success = false;
}
}
if (success)
{
i.NeedsProcessing = false;
}
}
}
更新(2010-01-18,美国东部标准时间下午 1:03) 这可能是迄今为止我能够提供的最有用的信息。
我再次查看 IIS 日志。发送登录请求后,我可以刷新日志并立即显示。但是,在我关闭控制台应用程序之前,不会显示任何页面请求。这是日志的相关位:
2011-01-18 17:44:54 X.X.X.X POST /MySite/login.aspx - 80 - X.X.X.X - 302 0 0 148
2011-01-18 17:44:54 X.X.X.X GET /MySite/default.aspx - 80 AutomatedUser X.X.X.X - 200 0 0 48
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_ONE&area=US 80 AutomatedUser X.X.X.X - 200 0 995 579100
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_ONE&area=CANADA 80 AutomatedUser X.X.X.X - 200 0 995 553247
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_TWO&area=US 80 AutomatedUser X.X.X.X - 200 0 995 532824
对 process.aspx 的每个 GET 请求都对应于对上述 RequestPage 方法的调用。行“request.GetResponse();” 只需要大约 10 秒左右,但在我关闭应用程序之前,该请求似乎永远不会完成(至少根据 IIS)。(如果您查看每一行的最后一个数字,这就是以毫秒为单位提供页面所需的时间,但我在应用程序中得到响应的时间要短得多。)所以这是可能的(甚至可能) IIS 正在限制它将从一个 IP 接受的连接数量。
这让我想到了一个问题:我提出的请求是什么导致他们保持“开放”状态?
请求不返回 HTML 页面(如果重要),它们返回 PDF。