想要通过libcurl使用https访问网址,需要配置CA证书。
这篇文章记录一下如何配置。
VS2022 添加了libcurl库
代码:
主函数,指定了访问"https://www.baidu.com"
int main()
{
curl_global_init(CURL_GLOBAL_WIN32);
const char* url = "https://www.baidu.com";
MyGetInfo(url);
curl_global_cleanup();
cout << "program end." << endl;
}
libcurl api实现访问,这里没有设置跟SSL有关的选项,
实际上是个http访问的代码。
int MyGetInfo(const char* url)
{
double content_length;
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HEADER, 1L);//仅HTTP头
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //在控制台显示详细信息
CURLcode ret = curl_easy_perform(curl);
if (ret != CURLE_OK) {
curl_easy_cleanup(curl);
return ERROR2("curl_easy_perform", ret);
}
else {
//获取HTTP头中的CURLINFO_CONTENT_LENGTH_DOWNLOAD信息
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
}
}
else {
return ERROR("curl_easy_init");
}
curl_easy_cleanup(curl);
return 0;
}
控制台输出执行结果(要设置CURLOPT_VERBOSE):
* Host www.baidu.com:443 was resolved.
* IPv6: 2409:8c20:6:1135:0:ff:b027:210c, 2409:8c20:6:1d55:0:ff:b09c:7d77
* IPv4: 36.155.132.76, 36.155.132.3
* Trying [2409:8c20:6:1135:0:ff:b027:210c]:443...
* Connected to www.baidu.com (2409:8c20:6:1135:0:ff:b027:210c) port 443
* ALPN: curl offers h2,http/1.1
* SSL certificate problem: unable to get local issuer certificate
* Closing connection
?MyGetInfo@@YAHPEBD@Z curl_easy_perform 60 error
program end.
可以看到,试图访问目标443端口,但是因为
SSL certificate problem: unable to get local issuer certificate
失败了。
修改代码:
int MyGetInfo(const char* url)
{
double content_length;
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HEADER, 1L);//仅HTTP头,不要数据
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //在控制台显示详细信息
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //新增
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);//新增
CURLcode ret = curl_easy_perform(curl);
if (ret != CURLE_OK) {
curl_easy_cleanup(curl);
return ERROR2("curl_easy_perform", ret);
}
else {
//获取HTTP头中的CURLINFO_CONTENT_LENGTH_DOWNLOAD信息
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
}
}
else {
return ERROR("curl_easy_init");
}
curl_easy_cleanup(curl);
return 0;
}
新增了以下代码:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //新增
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);//新增
CURLOPT_SSL_VERIFYPEER和CURLOPT_SSL_VERIFYHOST要一起设置,
都设置为0的时候,将忽略对CA证书的检查。
libcurl API解释:
CURLOPT_SSL_VERIFYHOST
When the verify value is 0, the connection succeeds regardless of the names in the certificate. Use that ability with caution!
CURLOPT_SSL_VERIFYPEER
When this option is disabled (set to zero), the CA certificates are not loaded and the peer certificate verification is simply skipped.
控制台输出执行结果(要设置CURLOPT_VERBOSE):
* Host www.baidu.com:443 was resolved.
* IPv6: 2409:8c20:6:1135:0:ff:b027:210c, 2409:8c20:6:1d55:0:ff:b09c:7d77
* IPv4: 36.155.132.76, 36.155.132.3
* Trying [2409:8c20:6:1135:0:ff:b027:210c]:443...
* Connected to www.baidu.com (2409:8c20:6:1135:0:ff:b027:210c) port 443
* ALPN: curl offers h2,http/1.1
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
* subject: C=CN; ST=beijing; L=beijing; O=Beijing Baidu Netcom Science Technology Co., Ltd; CN=baidu.com
* start date: Jul 6 01:51:06 2023 GMT
* expire date: Aug 6 01:51:05 2024 GMT
* issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Certificate level 0: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/1.x
> HEAD / HTTP/1.1
Host: www.baidu.com
Accept: */*
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Cache-Control: no-cache
Cache-Control: no-cache
< Connection: keep-alive
Connection: keep-alive
< Content-Length: 227
Content-Length: 227
< Content-Security-Policy: frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
Content-Security-Policy: frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
< Content-Type: text/html
Content-Type: text/html
< Date: Mon, 25 Dec 2023 05:50:16 GMT
Date: Mon, 25 Dec 2023 05:50:16 GMT
< Pragma: no-cache
Pragma: no-cache
< Server: BWS/1.1
Server: BWS/1.1
< Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
< Set-Cookie: PSTM=1703483416; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1703483416; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
< Set-Cookie: BAIDUID=2CF2E2EBB535C6E704A28FC977754E61:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000
Set-Cookie: BAIDUID=2CF2E2EBB535C6E704A28FC977754E61:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000
< Set-Cookie: BAIDUID_BFESS=2CF2E2EBB535C6E704A28FC977754E61:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None
Set-Cookie: BAIDUID_BFESS=2CF2E2EBB535C6E704A28FC977754E61:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None
< Traceid: 1703483416046571265014818631086766562759
Traceid: 1703483416046571265014818631086766562759
< X-Ua-Compatible: IE=Edge,chrome=1
X-Ua-Compatible: IE=Edge,chrome=1
<
* Connection #0 to host www.baidu.com left intact
program end.
可以看到,成功通过443端口通信了。但是仍然有以下一句log:
SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
首先获取百度的CA证书。
通过浏览器(我用的edge)访问百度。
点击地址栏左侧的小锁头图标,选择连接安全,
点击右上角的证书图标,
在证书查看器的详细信息中,右下角导出,可以保存.crt文件文件到本地,到处完成后我给改成.pem文件了。
代码:
int MyGetInfo(const char* url)
{
double content_length;
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HEADER, 1L);//仅HTTP头,不要数据
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //在控制台显示详细信息
//https
CURLcode err = curl_easy_setopt(curl, CURLOPT_CAINFO, "D:\\SourceCode\\http_file_download_vc\\http_libcurl_head_test_vc\\http_libcurl_head_test_vc\\baidu.pem"); //新增
if (err != CURLE_OK) {
cout << "CURLOPT_CAPATH err:" << err << endl;
}
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); //新增
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);//新增
CURLcode ret = curl_easy_perform(curl);
if (ret != CURLE_OK) {
curl_easy_cleanup(curl);
return ERROR2("curl_easy_perform", ret);
}
else {
//获取HTTP头中的CURLINFO_CONTENT_LENGTH_DOWNLOAD信息
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
}
}
else {
return ERROR("curl_easy_init");
}
curl_easy_cleanup(curl);
return 0;
}
通过CURLOPT_CAINFO设置了.pem文件的绝对路径,
CURLOPT_SSL_VERIFYPEER和CURLOPT_SSL_VERIFYHOST也都激活了。
控制台输出执行结果(要设置CURLOPT_VERBOSE):
* Host www.baidu.com:443 was resolved.
* IPv6: 2409:8c20:6:1135:0:ff:b027:210c, 2409:8c20:6:1d55:0:ff:b09c:7d77
* IPv4: 36.155.132.76, 36.155.132.3
* Trying [2409:8c20:6:1135:0:ff:b027:210c]:443...
* Connected to www.baidu.com (2409:8c20:6:1135:0:ff:b027:210c) port 443
* ALPN: curl offers h2,http/1.1
* CAfile: D:\SourceCode\http_file_download_vc\http_libcurl_head_test_vc\http_libcurl_head_test_vc\baidu.pem
* CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
* subject: C=CN; ST=beijing; L=beijing; O=Beijing Baidu Netcom Science Technology Co., Ltd; CN=baidu.com
* start date: Jul 6 01:51:06 2023 GMT
* expire date: Aug 6 01:51:05 2024 GMT
* subjectAltName: host "www.baidu.com" matched cert's "*.baidu.com"
* issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018
* SSL certificate verify ok.
* Certificate level 0: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/1.x
> HEAD / HTTP/1.1
Host: www.baidu.com
Accept: */*
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Cache-Control: no-cache
Cache-Control: no-cache
< Connection: keep-alive
Connection: keep-alive
< Content-Length: 227
Content-Length: 227
< Content-Security-Policy: frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
Content-Security-Policy: frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
< Content-Type: text/html
Content-Type: text/html
< Date: Mon, 25 Dec 2023 05:58:59 GMT
Date: Mon, 25 Dec 2023 05:58:59 GMT
< Pragma: no-cache
Pragma: no-cache
< Server: BWS/1.1
Server: BWS/1.1
< Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
< Set-Cookie: PSTM=1703483939; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1703483939; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
< Set-Cookie: BAIDUID=F12F8B0D2BD1D3F50FB25A3C594BAA7D:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000
Set-Cookie: BAIDUID=F12F8B0D2BD1D3F50FB25A3C594BAA7D:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000
< Set-Cookie: BAIDUID_BFESS=F12F8B0D2BD1D3F50FB25A3C594BAA7D:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None
Set-Cookie: BAIDUID_BFESS=F12F8B0D2BD1D3F50FB25A3C594BAA7D:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None
< Traceid: 1703483939153945447410347613991833952090
Traceid: 1703483939153945447410347613991833952090
< X-Ua-Compatible: IE=Edge,chrome=1
X-Ua-Compatible: IE=Edge,chrome=1
<
* Connection #0 to host www.baidu.com left intact
program end.
可以看到,SSL校验SSL certificate verify ok.
,是成功校验了证书的。
通过wireshark,也可以看到通信流程:
libcurl:https认证控制参数简介