您好!我正在尝试登录网站并下载授权 页。目前,该网站不需要任何身份验证 schema(我从响应头中找到了这个)。名称和密码是 只是通过PHP脚本验证(我想是这样)。登录页面是 “http://example.com/dashboard/index.php”。和我想要的页面 下载是“http://example.com/dashboard/dashboard.php”。 Chrome是 正常显示仪表板页面。但总是在cpp代码之下 在POST请求后甚至下载登录页面。那有什么不对 在里面?这个html代码是登录页面的表单。提前谢谢!
**************************************************************
<form name="login_form" action="" method="post" id="login_form">
<div class="full mar2">
<div class="login-left">Username</div>
<div class="login-right">
<label>
<input type="text" name="username" value="" class="user" />
</label>
</div>
</div>
<div class="full mar2">
<div class="login-left">Password</div>
<div class="login-right">
<label>
<input type="password" name="pswd" value="" class="user" />
</label>
</div>
</div>
<div class="full mar2">
<div class="login-left"> </div>
<div class="login-right"><input type="submit" value="" name="sub_login" class="log-in" /></div>
</div>
<input type="hidden" name="sub_check" value="1" id="sub_check" />
</form>
*******************************************************************
string GetHTMLTextFromWWW()
{
HINTERNET hSess;
hSess = WinHttpOpen(
L"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
if (!hSess) return "";
HINTERNET hConn;
hConn = WinHttpConnect(
hSess,
L"www.example.com",
INTERNET_DEFAULT_PORT,
0);
if (!hConn)
{
WinHttpCloseHandle(hSess);
return "";
}
HINTERNET hReq;
hReq = WinHttpOpenRequest(
hConn,
L"POST",
L"/dashboard",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH);
if (!hReq)
{
WinHttpCloseHandle(hConn);
WinHttpCloseHandle(hSess);
return "";
}
BOOL bRes;
// I got the names from login page's html form
char* data = "username=aan1982&pswd=admin1234&sub_check=1&sub_login=";
WinHttpSendRequest(
hReq,
L"Content-Type: application/x-www-form-urlencoded\r\n",
-1,
(LPVOID)data,
strlen(data),
strlen(data),
0);
bRes = WinHttpReceiveResponse(hReq, NULL);
if (!bRes)
{
WinHttpCloseHandle(hReq);
WinHttpCloseHandle(hConn);
WinHttpCloseHandle(hSess);
return "";
}
WinHttpCloseHandle(hReq);
//...
hReq = WinHttpOpenRequest(
hConn,
L"GET",
L"/dashboard/dashboard.php",
NULL,
L"http://example.com/dashboard/index.php",
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH);
if (!hReq)
{
WinHttpCloseHandle(hConn);
WinHttpCloseHandle(hSess);
return "";
}
WinHttpSendRequest(
hReq,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0);
bRes = WinHttpReceiveResponse(hReq, NULL);
if (!bRes)
{
WinHttpCloseHandle(hReq);
WinHttpCloseHandle(hConn);
WinHttpCloseHandle(hSess);
return "";
}
DWORD cbSize(0);
DWORD cbDownloaded;
string Text = "";
char *Buffer;
do
{
cbSize = 0;
if (WinHttpQueryDataAvailable(hReq, &cbSize))
{
Buffer = new (nothrow) char[cbSize + 1];
if (Buffer)
{
ZeroMemory(Buffer, cbSize + 1);
if (WinHttpReadData(hReq, (LPVOID)Buffer, cbSize, &cbDownloaded))
Text += Buffer;
delete [] Buffer;
}
}
} while (cbSize > 0);
WinHttpCloseHandle(hReq);
WinHttpCloseHandle(hConn);
WinHttpCloseHandle(hSess);
return Text;
}
答案 0 :(得分:0)
如果是简单的身份验证,您必须执行以下步骤:
hSess = WinHttpOpen(..);
hConn = WinHttpConnect(hSess, ..);
hReq = WinHttpOpenRequest(hConn, L"GET", ..); // create get request
WinHttpSendRequest(hReq, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
告知HTTP服务器您的意图WinHttpReceiveResponse(hReq, ..);
WinHttpQueryHeaders(hReq, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, ..);
WinHttpQueryHeader(..)
返回的状态为HTTP_STATUS_NOT_FOUND
,则由于HTTP服务器无法提供数据而停止。WinHttpQueryHeader(..)
返回的状态为HTTP_STATUS_OK
,则使用WinHttpQueryDataAvailable(hReq, ..)
和WinHttpReadData(hReq, ..)
检索数据,然后继续执行步骤10. WinHttpQueryHeader(..)
返回的状态为HTTP_STATUS_DENIED
,则WinHttpQueryAuthSchemes(hReq, &dwSupportedSchemes, &dwFirstScheme, &dwAuthTarget);
选择一种身份验证方法,并使用您的用户名和密码以最简单的方式调用WinHttpSetCredentials(hReq, dwAuthTarget, dwFirstScheme, ..);
。成功完成后,请返回步骤4.(如果您第二次来到这里,您的用户名和/或密码无效)如果你想我可以为此提供代码,但我必须从更大的代码中提取它,这需要一段时间......
如果服务器使用cookie作为身份验证,由于WinHttp无法处理cookie(或者至少我无法使其正确处理cookie),因此它变得更加复杂。我从后到前搜索过互联网并没有找到答案,但经过漫长的夜晚,我设法得到了一个有效的实施方案(仅适用于我的特殊情况)。
我希望这个简短的解释有所帮助。如果你需要我的实施,我会在这里发布。
编辑25 / Oct / 2014:
看起来我也错过了你的问题!我上面的解释是如何使用身份验证方案。
这是我从我的实现中提取的一段代码,它发送POST请求并读取响应。我将它与你的例子相匹配,但我没有尝试也没有编译它:
BOOL bResult;
DWORD dwRead;
DWORD dwDownloaded;
DWORD dwTotalSize;
char *pBuffer;
DWORD dwSize;
DWORD dwStatusCode;
char buffer[1024 * 128];
DWORD len;
hRequest = WinHttpOpenRequest(hConnection,
L"POST",
L"http://example.com/dashboard/dashboard.php",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
if (hRequest != NULL)
{
len = (DWORD)strlen("username=aan1982&pswd=admin1234&sub_check=1&sub_login=");
bResult = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
"username=aan1982&pswd=admin1234&sub_check=1&sub_login=",
len,
len,
0);
if (bResult != FALSE)
{
if (WinHttpReceiveResponse(hRequest, NULL) != FALSE)
{
dwSize = sizeof(dwStatusCode);
bResult = WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&dwStatusCode,
&dwSize,
NULL);
if (bResult != FALSE)
{
switch (dwStatusCode)
{
case HTTP_STATUS_OK:
pBuffer = buffer;
dwTotalSize = 0;
do
{
dwSize = 0;
if (WinHttpQueryDataAvailable(hRequest, &dwSize) != FALSE)
{
dwRead = dwSize;
if (dwRead > sizeof(buffer))
dwRead = sizeof(buffer);
bResult = WinHttpReadData(hRequest,
pBuffer,
dwRead,
&dwDownloaded);
if (bResult == FALSE)
{
printf("Failed to read data (error: %d)\n", GetLastError());
break;
}
else
{
pBuffer += dwDownloaded;
dwTotalSize += dwDownloaded;
}
}
}
while (dwSize > 0);
/*
** TODO:
** Write buffer to file or process it...
*/
break; /* HTTP_STATUS_OK */
case HTTP_STATUS_DENIED:
printf("access denied!\n");
break; /* HTTP_STATUS_DENIED */
case HTTP_STATUS_NOT_FOUND:
printf("file not found\n");
break; /* HTTP_STATUS_NOT_FOUND */
default:
printf("WinHttpQueryHeaders(..): dwStatusCode=%d\n", dwStatusCode);
break; /* default */
} /* switch (dwStatusCode) */
}
else /* if (bResult != FALSE) */
{
printf("WinHttpQueryHeaders(..) failed (error: %d)\n", GetLastError());
}
}
else /* if (WinHttpReceiveResponse(hRequest, NULL) != FALSE) */
{
printf("WinHttpReceiveResponse(..) failed (error: %d)\n", GetLastError());
}
}
else /* if (bResult != FALSE) */
{
printf("Failed to send request (error: %d)\n", GetLastError());
}
}
else /* if (http->hRequest != NULL) */
{
printf("Failed to open request (error: %d)\n", GetLastError());
}
此外,我建议使用HttpFox(FireFox插件)。使用该工具,您可以监控FireFox完成的HTTP请求。这对于了解正在发生的事情很有用,这是开始实施它的好地方。
让我知道它是否有效......