Libcurl POST请求在Windows 7出现SSL问题,Windows 10正常,求原因
Windows 7下libcurl HTTPS请求出现SSL问题(Windows 10正常)
我尝试在Windows 7操作系统上向我的HTTPS REST API发送简单POST请求并接收响应,当前防火墙已关闭,证书放置在.exe目录中。以下是我使用的代码:
std::string postRequest(std::string json, std::string endpoint,std::string code,std::string patchOrPOST,std::string source) { CURL* curl; CURLcode res; std::string response; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); std::string authorization = "Authorization: Basic " + code, portApiHttp = "Referer: " + portAPI + "/index.html", origin = "Origin: " + portAPI;//X-Requested-With: XMLHttpRequest struct curl_slist* headers = NULL; if (curl) { headers = curl_slist_append(headers, "Connection: keep-alive"); headers = curl_slist_append(headers, "Content-Length: "+(int)strlen(json.c_str())); headers = curl_slist_append(headers, authorization.c_str()); headers = curl_slist_append(headers, "Accept: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json"); if (source.size() != 0) { headers = curl_slist_append(headers, source.c_str()); } headers = curl_slist_append(headers, R"(sec-ch-ua: "Chromium";v="91")"); headers = curl_slist_append(headers, "sec-ch-ua-mobile: ?0"); headers = curl_slist_append(headers, "X - Requested - With: XMLHttpRequest"); headers = curl_slist_append(headers, origin.c_str()); headers = curl_slist_append(headers, "Sec-Fetch-Site: same-origin"); headers = curl_slist_append(headers, "Sec-Fetch-Mode: cors"); headers = curl_slist_append(headers, "Sec-Fetch-Dest: empty"); headers = curl_slist_append(headers, portApiHttp.c_str()); headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate, br"); headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.9"); curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str()); curl_easy_setopt(curl, CURLOPT_CAINFO, "ca-bundle.crt"); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); if (patchOrPOST == "PATCH") { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); } else if (patchOrPOST == "PUT") { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); } else if (patchOrPOST == "GET") { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); } else if(patchOrPOST=="DELETE") { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); } //curl_easy_setopt(curl, CURLOPT_PROXY, "127.0.0.1:8888"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50L); curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); if (patchOrPOST != "GET") { curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, json.size()); curl_easy_setopt(curl, CURLOPT_POST, 1); } res= curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); if (res!= CURLE_OK) { curl_easy_cleanup(curl); return "ERROR"; } res= curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); if (res!= CURLE_OK) { curl_easy_cleanup(curl); return "ERROR"; } res = curl_easy_perform(curl); long http_code; /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); return response; }
问题原因及解决方法
1. TLS版本兼容性限制
Windows 7默认仅支持TLS 1.0和TLS 1.1,而现代REST API普遍要求TLS 1.2或更高版本。即使使用libcurl,若依赖系统自带的Schannel SSL库,也会因TLS版本不匹配导致握手失败。
- 解决:
- 在代码中强制指定TLS版本,添加:
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - 给Windows 7安装KB3140245补丁,该补丁是Win7支持TLS 1.2的必要系统更新。
- 在代码中强制指定TLS版本,添加:
2. libcurl编译后端差异
如果Win10版本的libcurl静态编译了OpenSSL,而Win7版本依赖系统Schannel,两者的SSL处理逻辑、证书支持存在差异;或者Win7使用的libcurl版本过旧,不支持现代TLS特性。
- 解决:
- 为Win7编译或使用静态链接最新OpenSSL版本的libcurl,避免依赖系统Schannel。
- 确保libcurl版本不低于7.60,该版本开始对TLS 1.2+的支持更完善。
3. 证书路径问题
Windows 7下程序的当前工作目录可能并非exe所在目录(比如通过快捷方式启动),导致libcurl无法找到相对路径的ca-bundle.crt。
- 解决:
使用绝对路径指定证书文件,可通过获取程序路径拼接证书名:#include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") char exePath[MAX_PATH]; GetModuleFileNameA(NULL, exePath, MAX_PATH); PathRemoveFileSpecA(exePath); std::string caPath = std::string(exePath) + "\\ca-bundle.crt"; curl_easy_setopt(curl, CURLOPT_CAINFO, caPath.c_str());
4. 代码中的潜在缺陷
代码中的一些逻辑可能间接引发SSL相关异常:
- 手动设置
Content-Length头:容易出现长度计算错误,导致请求异常,建议删除该头,让libcurl自动处理。 - 请求方法逻辑混乱:非GET请求时同时设置
CURLOPT_CUSTOMREQUEST和CURLOPT_POST=1,会导致请求方法被覆盖(比如PATCH被当成POST),引发服务器端异常,可能被误判为SSL问题。调整逻辑:非POST方法仅使用CURLOPT_CUSTOMREQUEST,且GET请求不要设置CURLOPT_POSTFIELDS。 CURLOPT_SSL_VERIFYPEER=0:禁用证书验证无法解决TLS版本不兼容问题,且存在安全风险,建议仅用于测试,正式环境需正确配置证书。
内容的提问来源于stack exchange,提问作者Prestige
相关产品推荐
相关产品推荐

