如何使用 WinInet 发送 HTTPS 请求?

Posted

技术标签:

【中文标题】如何使用 WinInet 发送 HTTPS 请求?【英文标题】:How to send HTTPS request using WinInet? 【发布时间】:2013-09-20 06:45:45 【问题描述】:

我想使用 WinInet 发送 HTTPS GET 请求。据我所知,除了我必须使用 INTERNET_DEFAULT_HTTPS_PORTINTERNET_FLAG_SECURE 标志之外,我应该像发送 HTTP 请求一样执行此操作。

所以这是我尝试过的:

#include "stdafx.h"
#include <string>
#include <windows.h>
#include <WinInet.h>

#pragma comment (lib, "Wininet.lib")

using namespace std;


// convert string
wstring CharPToWstring(const char* _charP)

    return wstring(_charP, _charP + strlen(_charP));


// send https request
wstring SendHTTPSRequest_GET(const wstring& _server,
                             const wstring& _page,
                             const wstring& _params = L"")

    char szData[1024];

    // initialize WinInet
    HINTERNET hInternet = ::InternetOpen(TEXT("WinInet Test"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hInternet != NULL) 
    
        // open HTTP session
        HINTERNET hConnect = ::InternetConnect(hInternet, _server.c_str(), INTERNET_DEFAULT_HTTPS_PORT, NULL,NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 1);
        if (hConnect != NULL) 
        
            wstring request = _page + 
                    (_params.empty() ? L"" : (L"?" + _params));

            // open request
            HINTERNET hRequest = ::HttpOpenRequest(hConnect, L"GET", (LPCWSTR)request.c_str() ,NULL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 1);
            if (hRequest != NULL) 
               
                // send request
                BOOL isSend = ::HttpSendRequest(hRequest, NULL, 0, NULL, 0);

                if (isSend)
                
                    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;
                    
                

                // close request
                ::InternetCloseHandle(hRequest);
            
            // close session
            ::InternetCloseHandle(hConnect);
        
        // close WinInet
       ::InternetCloseHandle(hInternet);
    

    wstring answer = CharPToWstring(szData);

    return answer;



int _tmain(int argc, _TCHAR* argv[])

    wstring answer = SendHTTPSRequest_GET(L"www.site.com", L"page.php", L"param1=value1&param2=value2&param3=value3&param4=value4");

    return 0;

我的函数返回了一个答案:

<html>

<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>

<body bgcolor="white">

<center><h1>400 Bad Request</h1></center>

<center>The plain HTTP request was sent to HTTPS port</center>

<hr><center>nginx/1.0.10</center>

</body>

</html>

我做错了什么?

【问题讨论】:

【参考方案1】:

INTERNET_FLAG_SECURE 应在 HttpOpenRequest 的标志中使用,而不是 InternetConnect

这在the MSDN documentation for WinINet API flags中有解释:

INTERNET_FLAG_SECURE

0x00800000

使用安全事务语义。这转化为使用安全套接字层/私有通信技术 (SSL/PCT),并且仅在 HTTP 请求中有意义。该标志由HttpOpenRequest 和InternetOpenUrl 使用,但如果https:// 出现在URL 中,则这是多余的。 InternetConnect 函数将此标志用于 HTTP 连接;在此连接下创建的所有请求句柄都将继承此标志。

【讨论】:

@IgorSkochinsky,也许你知道如果使用 winInet api 我可以传递与服务器 URL 本身分离的不同 SNI .. 我目前正在使用 winhttp 并没有找到任何设置不同于 URL 的 SNI 值的方法(使用WinHttpConnect @IgorSkochinsky,基本上以下问题使用 winhttp API 讨论了完全相同的问题https://***.com/questions/57479973/starting-https-connection-with-ip-address-and-sni。它没有任何答案,但我认为如果您可以使用 winhttp 或 wininet 提供任何解决方案,那就太好了:-)

以上是关于如何使用 WinInet 发送 HTTPS 请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中使用 wininet 创建 POST 请求

使用 Wininet 发送多个 Http 请求

在 C++ 中使用 Wininet 发送 POST 请求时的编码问题

使用wininet的异步请求

WinINet:如何防止 HttpSendRequest 跟随重定向(30x 状态代码)?

在 C++ 中使用 wininet