我有一个VC ++ HttpPOST方法,适用于80和443端口。 (在google.com等热门网站上)
现在当我连接到具有cgi脚本的安全主机(172.17.9.93)时,现在当我使用 fiddler 进行连接时,我收到一个无效证书警告的警告接受警告我能够连接。
我必须在C ++中使用相同的行为来忽略证书,使用下面的标记 SECURITY_FLAG_IGNORE_UNKNOWN_CA
, INTERNET_FLAG_IGNORE_CERT_CN_INVALID
以及一些组合函数 HttpOpenRequest()但它失败并给出以下输出。
C ++控制台输出
172.17.9.93 : 443 data base-bin/hello.cgi
Error 12045 has occurred while HttpSendRequest
INVALID CA request received (12045)
源代码VC ++
#define _WIN32_WINNT 0x600
#include <windows.h>
#include <stdio.h>
#include <string>
#include <wininet.h>
#pragma comment(lib,"Wininet.lib")
using namespace std;
int doPost(std::string send, std::string &receive, LPCTSTR host, int port, LPCTSTR url)
{
char szData[1024];
int winret = 0;
TCHAR szAccept[] = L"*/*";
LPWSTR AcceptTypes[2] = { 0 };
AcceptTypes[0] = szAccept;
HINTERNET hInternet = ::InternetOpen(TEXT("mandar"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet != NULL)
{
printf("\n %S : %d data %S \n", host, port, url);
// open HTTP session
HINTERNET hConnect;
if (port == 80)
{
hConnect = ::InternetConnect(hInternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 0);
}
else
{
hConnect = ::InternetConnect(hInternet, host, port, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 0);
}
if (hConnect != NULL)
{
DWORD dwFlags = dwFlags |= INTERNET_FLAG_SECURE |
SECURITY_FLAG_IGNORE_UNKNOWN_CA | INTERNET_FLAG_IGNORE_CERT_CN_INVALID|
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
/*SECURITY_FLAG_IGNORE_UNKNOWN_CA |
INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
| SECURITY_FLAG_IGNORE_CERT_CN_INVALID
| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;*/
// open request
HINTERNET hRequest;
if (port == 80)
{
hRequest = ::HttpOpenRequest(hConnect, TEXT("POST"), url, HTTP_VERSION, NULL, 0, NULL, 0);
}
else
{
hRequest = ::HttpOpenRequest(hConnect, TEXT("POST"), url, HTTP_VERSION, NULL, 0, dwFlags, 0);
}
if (hRequest != NULL)
{
if (::HttpSendRequest(hRequest, NULL, 0, (LPVOID)send.c_str(), send.length()))
{
for (;;)
{
// reading data
DWORD dwByteRead;
BOOL isRead = ::InternetReadFile(hRequest, szData, sizeof(szData) - 1, &dwByteRead);
// break cycle if error or end
if (isRead == FALSE || dwByteRead == 0)
break;
// saving result
szData[dwByteRead] = 0;
receive.append(szData);
}
printf(" receive data [%s]", receive.c_str());
}
else{
winret = GetLastError();
printf("\nError %d has occurred while HttpSendRequest", winret);
switch (winret)
{
case ERROR_INTERNET_INVALID_CA:
printf("\nINVALID CA request received (%d)\n", winret);
break;
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
printf("\nResubmitting for CLIENT_AUTH_CERT_NEEDED (%d)\n", winret);
break;
default:
printf("\nError %d has occurred while HttpSendRequest", winret);
}
}
// close request
::InternetCloseHandle(hRequest);
}
else{
winret = GetLastError();
printf("\nError %d has occurred while HttpOpenRequest", winret);
}
// close session
::InternetCloseHandle(hConnect);
}
else{
winret = GetLastError();
printf("\nError %d has occurred while InternetConnect", winret);
}
// close WinInet
::InternetCloseHandle(hInternet);
}
else
{
winret = GetLastError();
printf("\nError %d has occurred while InternetOpen", winret);
}
return winret;
}
int main()
{
std::string send;
std::string receive;
LPCTSTR host = L"172.17.9.93";
int port = 443;// 80;
LPCTSTR url = L"base-bin/hello.cgi";
doPost("<XMLhello>1</XMLhello>",receive,host,port,url);
}
答案 0 :(得分:1)
HttpOpenRequest
只能使用INTERNET_FLAG_*
标记 - 将标记SECURITY_FLAG_IGNORE_UNKNOWN_CA
传递给HttpOpenRequest
这是错误。
寻找数值:
#define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100
#define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100 // asking wininet to add "pragma: no-cache"
因此,如果您尝试将SECURITY_FLAG_IGNORE_UNKNOWN_CA
传递给HttpOpenRequest
,那么您确实会传递INTERNET_FLAG_PRAGMA_NOCACHE
旗帜
SECURITY_FLAG_IGNORE_UNKNOWN_CA
旨在InternetSetOption
功能与INTERNET_OPTION_SECURITY_FLAGS
因此您需要使用此代码:
DWORD dwFlags;
DWORD dwBuffLen = sizeof(dwFlags);
if (InternetQueryOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen))
{
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags));
}
还阅读了How To Handle Invalid Certificate Authority Error with WinInet - 方法2.没有用户界面:就是你的情况
答案 1 :(得分:0)
第一个答案非常准确,但我遇到了有关 WinInet-API 的另一个特点:
示例:
// First Request...
if (!HttpSendRequest(hRequest, ...) && GetLastError() == ERROR_INTERNET_INVALID_CA)
{
DWORD dwFlags = 0;
DWORD dwBuffLen = sizeof(dwFlags);
if (InternetQueryOption(hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen))
{
dwFlags |= SECURITY_SET_MASK;
InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));
}
if(HttpSendRequest(hRequest, ...))
/* ssl errors were ignores successfully */
else
/* still ssl error (should not happen) */
}