C++发起Https请求

Wininet库忽略Https证书
复制代码
相信很多朋友使用C++ WINAPI开发的时候网络模块的时候遇到Https忽悠证书无效的情况下,
仍然希望获取结果下列代码便是忽略异常的Https CA证书,下面对原理进行简单的讲解首先,
需要设置Https忽略需要用到如下结果函数与参数InternetQueryOptionA/InternetSetOptionA
参数需要SECURITY_FLAG_IGNORE_UNKNOWN_CA,下面建议先阅读下代码可以发现忽略Https证书
是发生在HttpSendRequestA之后设置这是因为InternetConnect主要负责主要负责建立与服务器
的连接,而涉及到CA(Certificate Authority)的验证通常是在建立连接后的HTTP请求阶段进行的,
CA的验证是在SSL/TLS握手过程中完成的,而握手过程通常是在 HttpSendRequestA被调用时发生。
因此,在建立连接时,我们还没有进入HTTP请求的阶段,所以无法在 InternetConnect 之前
处理CA验证的问题,因此下列代码是进行这样忽略的首先HttpSendRequestA返回ERROR_INTERNET_INVALID_CA
出现CA证书异常这个时候需要忽略证书无效,InternetQueryOptionA获取当前的安全选项然后
追加上SECURITY_FLAG_IGNORE_UNKNOWN_CA忽略证书无效CA将设置后的值通过InternetSetOptionA 
函数应用再次发起HttpSendRequestA即可忽略CA证书进行下一步操作。
cpp 复制代码
#include <Windows.h>
#include <Wininet.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")

#define TRANSFER_SIZE 1024

// 定义一个函数来执行HTTP请求
bool PerformHttpRequest() {
    // 设置用户代理字符串
    LPCSTR lpszAgent = "";
    // 初始化WinINet会话
    HINTERNET hInternet = InternetOpenA(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

    if (!hInternet) {
        return false; // 如果InternetOpen失败,返回false
    }

    // 服务器详情
    LPCSTR lpszServerName = "192.168.99.111"; // 设置服务器IP地址
    INTERNET_PORT nServerPort = INTERNET_DEFAULT_HTTPS_PORT; // HTTPS端口443
    LPCSTR lpszUserName = NULL; // 无登录用户名
    LPCSTR lpszPassword = NULL; // 无登录密码
    DWORD dwConnectFlags = 0;
    DWORD dwConnectContext = 0;

    // 连接到服务器
    HINTERNET hConnect = InternetConnectA(hInternet,
        lpszServerName, nServerPort,
        lpszUserName, lpszPassword,
        INTERNET_SERVICE_HTTP,
        dwConnectFlags, dwConnectContext);

    if (!hConnect) {
        InternetCloseHandle(hInternet);
        return false; // 如果连接失败,返回false
    }

    // 请求详情
    LPCSTR lpszVerb = "GET";
    LPCSTR lpszObjectName = "/Login";
    LPCSTR lpszVersion = NULL;    // 默认.
    LPCSTR lpszReferrer = NULL;   // 没有引用页
    LPCSTR* lplpszAcceptTypes = NULL; // Accpet所有类型.
    DWORD dwOpenRequestFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
        INTERNET_FLAG_KEEP_CONNECTION |
        INTERNET_FLAG_NO_AUTH |
        INTERNET_FLAG_NO_COOKIES |
        INTERNET_FLAG_NO_UI |
        // 设置启用HTTPS
        INTERNET_FLAG_SECURE |
        INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
        INTERNET_FLAG_RELOAD;
    DWORD dwOpenRequestContext = 0;

    // 初始化请求
    HINTERNET hRequest = HttpOpenRequestA(hConnect, lpszVerb, lpszObjectName, lpszVersion,
        lpszReferrer, lplpszAcceptTypes,
        dwOpenRequestFlags, dwOpenRequestContext);

    if (!hRequest) {
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果初始化请求失败,返回false
    }

    // 发送请求
    BOOL bResult = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);

    if (!bResult && GetLastError() == ERROR_INTERNET_INVALID_CA) {
        // 处理HTTPS证书无效的情况
        DWORD dwFlags;
        DWORD dwBuffLen = sizeof(dwFlags);
        InternetQueryOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwBuffLen);
        dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
        InternetSetOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));
        bResult = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
    }

    if (!bResult) {
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果发送请求失败,返回false
    }

    // 获取HTTP响应头信息
    char szBuff[TRANSFER_SIZE];
    DWORD dwReadSize = TRANSFER_SIZE;
    bResult = HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, szBuff, &dwReadSize, NULL);

    if (!bResult) {
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果获取响应头信息失败,返回false
    }

    szBuff[dwReadSize] = '\0';
    printf("%s\n", szBuff);

    // HTTP响应的正文
    DWORD dwBytesAvailable;
    bResult = InternetQueryDataAvailable(hRequest, &dwBytesAvailable, 0, 0);

    if (!bResult) {
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果查询可用数据失败,返回false
    }

    if (dwBytesAvailable > TRANSFER_SIZE) {
        printf("数据太长 %d /b", GetLastError(), dwBytesAvailable);
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果可用数据太长,返回false
    }

    DWORD dwBytesRead;
    bResult = InternetReadFile(hRequest, szBuff, dwBytesAvailable, &dwBytesRead);

    if (!bResult) {
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false; // 如果读取数据失败,返回false
    }

    szBuff[dwBytesRead] = '\0';
    printf("%s\n", szBuff);

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    return true; // 成功执行HTTP请求,返回true
}

int main() {
    if (PerformHttpRequest()) {
        return 0;
    }
    else {
        return 1;
    }
}
相关推荐
byxdaz5 分钟前
C++内存序
c++
扑火的小飞蛾17 分钟前
网络安全小白学习路线图 (基于提供文档库)
学习·安全·web安全
ghie909019 分钟前
基于MATLAB GUI的伏安法测电阻实现方案
开发语言·matlab·电阻
优雅的潮叭21 分钟前
c++ 学习笔记之 malloc
c++·笔记·学习
Gao_xu_sheng23 分钟前
Inno Setup(专业安装/更新 EXE)
开发语言
计算机程序设计小李同学29 分钟前
个人数据管理系统
java·vue.js·spring boot·后端·web安全
吴声子夜歌1 小时前
Java数据结构与算法——基本数学问题
java·开发语言·windows
wanglei2007082 小时前
生产者消费者
开发语言·python
leo__5202 小时前
基于菲涅耳衍射积分的空心高斯光束传输数值模拟(MATLAB实现)
开发语言·matlab
昵称已被吞噬~‘(*@﹏@*)’~2 小时前
【RL+空战】学习记录03:基于JSBSim构造简易空空导弹模型,并结合python接口调用测试
开发语言·人工智能·python·学习·深度强化学习·jsbsim·空战