Libcurl的编译_HTTP/HTTPS客户端源码示例

本文介绍使用Libcurl进行HTTPS客户端开发的方法,包括环境搭建、编译步骤、代码示例等,涵盖POST请求、文件上传及下载等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Libcurl的编译_HTTP/HTTPS客户端源码示例

标签: libcurl
  3372人阅读  评论(0)  收藏  举报

目录(?)[+]

HTTP/HTTPS客户端源码示例

环境:  zlib-1.2.8  openssl-1.0.1g  curl-7.36

Author:  Kagula

LastUpdateDate: 2016-05-09

阅读前提:CMake工具的基本使用、配置openssl-1.0.1g 开发环境

 

编译zlib库

         下载zlib-1.2.8.tar.gz并解压缩到" D:\SDK\zlib-1.2.8",使用CMake工具生成zlib.sln,在Visual Studio2013中打开并编译即可。

编译curl-7.36.0

    假设Open SSL已经安装到“D:\SDK\openssl-1.0.1g”,先设置下面的环境变量

OPENSSL_LIBRARIES=D:\SDK\openssl-1.0.1g\out32

OPENSSL_ROOT_DIR=D:\SDK\openssl-1.0.1g

    从http://curl.haxx.se/下载curl-7.36.0.zip并解压缩到“D:\SDK\curl-7.36.0”启动CMake工具Configure,分别设置LIB_EAY_RELEASESSL_EAY_RELEASE变量为“D:\SDK\openssl-1.0.1g\out32\libeay32.lib”,“D:\SDK\openssl-1.0.1g\out32\ssleay32.lib”,产生sln文件后打开,为里面的curl工程项目添加“USE_MANUAL”宏定义,然后build里面的4个项目成功。

   为项目添加链接库libcurl_imp.lib  , 把libcurl.dll文件复制到C++项目路径下,否则程序运行会提示找不到动态链接库。

下面是HTTP/HTTPS客户端示例


如何使用

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. #include <string>  
  3.   
  4. using namespace std;  
  5.   
  6. #include "httpclient.h"  
  7.   
  8. int main(int argc, char *argv[])  
  9. {  
  10.     string response;  
  11.   
  12.     //login  
  13.     kagula::network::CHttpClient client;  
  14.     int nR = client.Post("https://lijun:8443/escortcashbox/main/login.do",  
  15.                          "data={\"version\":\"1.0.0.0\",\"user\":\"admin\",\"password\":\"123\"}",                           
  16.                          response,true,  
  17.                          "d:\cookie.txt",  
  18.                          "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem",  
  19.                          "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem",  
  20.                          "123456");  
  21.     cout << nR << endl <<response << endl;  
  22.   
  23.     //upload png file  
  24.     /* 
  25.     std::map<std::string,std::string> mapFields; 
  26.     std::map<std::string,std::vector<std::string>> mapFiles; 
  27.     mapFields["data"] = "{\"version\":\"1.0.0.0\",\"socialid\":\"1012\",\"realname\":\"realnamevalue\",\"portrait\":\"protraitvalue\",\"fingerid\":\"fingeridvalue\",\"groupid\":\"123\"}"; 
  28.     std::vector<std::string> vecFile(2); 
  29.     vecFile[0] = "d:\\b.png"; 
  30.     vecFile[1] = "image/png"; 
  31.     mapFiles["portraitFile"] = vecFile; 
  32.     nR = client.MultipartFormdata("https://lijun:8443/escortcashbox/main/escortStaffAdd.do", 
  33.                                   mapFields,mapFiles, 
  34.                                   response, 
  35.                                   "d:\cookie.txt", 
  36.                                   "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem", 
  37.                                   "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem", 
  38.                                   "123456"); 
  39.  
  40.     cout << nR << endl << response << endl; 
  41. */  
  42.     //download png file  
  43.     nR = client.GetFile("https://lijun:8443/escortcashbox/upload/img/20160527_110514_679_426.png",  
  44.                         "d:/ee.png",  
  45.                         "d:\cookie.txt",  
  46.                         "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem",  
  47.                         "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem",  
  48.                         "123456");  
  49.     cout << nR << endl;  
  50.   
  51.     return 0;  
  52. }  


HttpClient.h封装好的头文件

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //HttpClient.h源代码清单  
  2. #ifndef _HTTPCLIENT_H_  
  3. #define _HTTPCLIENT_H_  
  4.   
  5. #include <string>  
  6. #include <map>  
  7. #include <vector>  
  8.   
  9. /* 
  10. Title: Get Response from Web Server by HTTP/HTTPS method. 
  11. Environment: 
  12. Windows 7SP1, Windows 8.1, Windows 10 
  13. QT Creator 3.5.1, Visual Studio 2013 Update1, Visual Studio 2013 Update5 
  14. libcurl 7.36.0, libcurl 7.46.0, Qt 5.6, MSYS2 64bits gcc 5.3.0 
  15. Last Update: 2016-05-27 
  16. Remark: 
  17. [1]如果要在多线程方式下同时调用多个CHttpClient实例, 
  18.  需要在App初始化的时候调用kagula::network::Init(); 
  19.  在App结束的时候调用kagula::network::Cleanup(); 
  20. [2]编译libcurl必须打开zlib标志,并且把OpenSSL也链进去。 
  21.  
  22. Reference: 
  23. curl_eay_setopt manual 
  24. http://www.helplib.net/s/linux.die/65_2740/man-3-curl-easy-setopt.shtml 
  25. C++ cout format 
  26. http://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html 
  27. */  
  28.   
  29. namespace kagula  
  30. {  
  31.     namespace network  
  32.     {  
  33.         void Init();  
  34.         void Cleanup();  
  35.   
  36.         class CHttpClient  
  37.         {  
  38.         public:  
  39.             CHttpClient(void);  
  40.             ~CHttpClient(void);  
  41.   
  42.         public:  
  43.             /** 
  44.             * @brief HTTP/HTTPS POST/GET请求 
  45.             * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com 
  46.             * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&… 
  47.             * @param strCookie 输入参数,Cookie文件名,例如 d:\temp\cookie.txt 
  48.             *                          如果为空,不启用Cookie. 
  49.             * @param strResponse 输出参数,返回的内容 
  50.             * @param bPost 是否Post方式发送请求,默认Post方式发送请求。 
  51.             * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性. 
  52.             * @param pClientCalPath 输入参数,为客户端证书的路径.如果输入为NULL,则不验证客户端证书的有效性. 
  53.             * @param pClientCalPassword 输入参数,为客户端证书的存取密码. 
  54.             * @return 返回是否Post成功 
  55.             * 0  成功 
  56.             * 7  无法连接 
  57.             * 28 超时 
  58.             * 58 服务端验证客户端证书失败。 
  59.             * 60 客户端验证服务端证书失败。 
  60.             */  
  61.             int Post(const char* pUrl,  
  62.                      const char* pPost,  
  63.                      std::string &strResponse,  
  64.                      bool bPost,  
  65.                      const char* pCookie,  
  66.                      const char* pCaPath = NULL,  
  67.                      const char* pClientCalPath = NULL,  
  68.                      const char* pClientCalPassword = NULL);  
  69.   
  70.             int MultipartFormdata(const char *pUrl,  
  71.                                   const std::map<std::string,std::string> & mapFields,  
  72.                                   const std::map<std::string,std::vector<std::string>> & mapFiles,  
  73.                                   std::string & strResponse,  
  74.                                   const char *pCookie,  
  75.                                   const char * pCaPath = NULL,  
  76.                                   const char * pClientCalPath = NULL,  
  77.                                   const char * pClientCalPassword = NULL);  
  78.   
  79.             int GetFile(const char* pUrl,  
  80.                         const char* pLocalFullPath,  
  81.                         const char* pCookie,  
  82.                         const char* pCaPath = NULL,  
  83.                         const char* pClientCalPath = NULL,  
  84.                         const char* pClientCalPassword = NULL);  
  85.         public:  
  86.             void SetDebug(bool bDebug);  
  87.             std::string getMsgInChinese(int code);  
  88.   
  89.         private:  
  90.             bool m_bDebug;  
  91.   
  92.             bool PrintCookies(void* curl, std::string& strOut);  
  93.         };  
  94.     }  
  95. }  
  96. #endif  


源文件清单

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //HttpClient.cpp源代码清单  
  2. #include "HttpClient.h"  
  3. #include <iostream>  
  4. #include <curl/curl.h>  
  5. #include <iomanip>  
  6. #include <sstream>  
  7.   
  8. #ifdef WIN32  
  9. #pragma comment(lib,"libcurl_imp.lib")  
  10. #endif  
  11.   
  12. namespace kagula  
  13. {  
  14.     namespace network  
  15.     {  
  16.         CHttpClient::CHttpClient(void) :  
  17.             m_bDebug(false)  
  18.         {  
  19.   
  20.         }  
  21.   
  22.         CHttpClient::~CHttpClient(void)  
  23.         {  
  24.   
  25.         }  
  26.   
  27.         bool CHttpClient::PrintCookies(void* curl, std::string& strOut)  
  28.         {  
  29.             std::ostringstream ostr;  
  30.   
  31.             CURLcode res;  
  32.             struct curl_slist *cookies;  
  33.   
  34.             res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);  
  35.             if (res != CURLE_OK) {  
  36.   
  37.                 ostr << "Curl curl_easy_getinfo failed:" << curl_easy_strerror(res) << std::endl;  
  38.                 strOut = ostr.str();  
  39.                 return false;  
  40.             }  
  41.             const struct curl_slist *nc = cookies;  
  42.             int i = 1;  
  43.             ostr << "Cookies, curl knows:" << std::endl;  
  44.             while (nc) {  
  45.                 ostr << "[" << i++ << "]: " << nc->data << std::endl;  
  46.                 nc = nc->next;  
  47.             }  
  48.   
  49.             return true;  
  50.         }  
  51.   
  52.         static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)  
  53.         {  
  54.             if (itype == CURLINFO_TEXT)  
  55.             {  
  56.                 //printf("[TEXT]%s\n", pData);  
  57.             }  
  58.             else if (itype == CURLINFO_HEADER_IN)  
  59.             {  
  60.                 printf("[HEADER_IN]%s\n", pData);  
  61.             }  
  62.             else if (itype == CURLINFO_HEADER_OUT)  
  63.             {  
  64.                 printf("[HEADER_OUT]%s\n", pData);  
  65.             }  
  66.             else if (itype == CURLINFO_DATA_IN)  
  67.             {  
  68.                 printf("[DATA_IN]%s\n", pData);  
  69.             }  
  70.             else if (itype == CURLINFO_DATA_OUT)  
  71.             {  
  72.                 printf("[DATA_OUT]%s\n", pData);  
  73.             }  
  74.             return 0;  
  75.         }  
  76.   
  77.         size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid)  
  78.         {  
  79.             std::string* str = reinterpret_cast<std::string*>(lpVoid);  
  80.             if (NULL == str || NULL == buffer)  
  81.             {  
  82.                 return -1;  
  83.             }  
  84.   
  85.             char* pData = reinterpret_cast<char*>(buffer);  
  86.             str->append(pData, size * nmemb);  
  87.             return nmemb;  
  88.         }  
  89.   
  90.         size_t OnWriteData_MultipartFormdata( void *inBuffer, size_t size, size_t nmemb, void *outBuffer )  
  91.         {  
  92.             int len = size * nmemb;  
  93.             char *temp = new char[len+1];  
  94.             memcpy(temp,inBuffer,len);  
  95.             temp[len]=0;  
  96.             reinterpret_cast<std::string *>(outBuffer)->append(temp);  
  97.             delete temp;  
  98.             return len;  
  99.         }  
  100.   
  101.         size_t OnWriteData_GetFile(void *inBuffer, int size, int nmemb, std::string &content)  
  102.         {  
  103.             long len = size * nmemb;  
  104.             std::string temp((char *)inBuffer, len);  
  105.             content += temp;  
  106.             return len;  
  107.         }  
  108.   
  109.         std::string CHttpClient::getMsgInChinese(int code)  
  110.         {  
  111.             switch(code)  
  112.             {  
  113.             case 0:  
  114.                 return "通讯成功";  
  115.             case 7:  
  116.                 return "服务器连接失败。";  
  117.             case 28:  
  118.                 return "连接超时。";  
  119.             case 58:  
  120.                 return "服务端验证客户端证书失败。";  
  121.             case 60:  
  122.                 return "客户端验证服务端证书失败。";  
  123.             default:  
  124.                 return "";  
  125.             }  
  126.         }  
  127.   
  128.         int CHttpClient::Post(const char* pUrl,  
  129.                               const char* pPost,  
  130.                               std::string & strResponse,  
  131.                               bool bPost,  
  132.                               const char* pCookie,  
  133.                               const char* pCaPath,  
  134.                               const char* pClientCalPath,  
  135.                               const char* pClientCalPassword)  
  136.         {  
  137.             strResponse = "";  
  138.   
  139.   
  140.             CURLcode res;  
  141.             CURL* curl = curl_easy_init();  
  142.             if (NULL == curl)  
  143.             {  
  144.                 return CURLE_FAILED_INIT;  
  145.             }  
  146.             if (m_bDebug)  
  147.             {  
  148.                 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
  149.                 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);  
  150.             }  
  151.             curl_easy_setopt(curl, CURLOPT_URL, pUrl);  
  152.             if(bPost)  
  153.             {  
  154.                 curl_easy_setopt(curl, CURLOPT_POST, 1);  
  155.                 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pPost);  
  156.             }  
  157.             curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
  158.             curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post);  
  159.             curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);  
  160.             curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  161.   
  162.             if (pCookie!=0)  
  163.             {  
  164.                 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);  
  165.                 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);  
  166.             }  
  167.   
  168.             if (NULL == pCaPath)  
  169.             {  
  170.                 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);  
  171.                 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);  
  172.   
  173.                 //需要在编译curl的时候,一同编译zlib标志。要不然找不到这个标志.  
  174.                 //当然前提是你已经编译完成zlib.  
  175.                 //发出接受gzip压缩内容的请求,如果服务器支持gzip内容,会返回压缩后的数据。  
  176.                 //如果Http服务器不支持gzip encoding也不影响libcurl正常工作。  
  177.                 //接受数据的时候,如果返回的是压缩数据,libcurl会自动解压数据。  
  178.                 curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");  
  179.             }  
  180.             else  
  181.             {  
  182.                 //缺省情况就是PEM,所以无需设置,另外支持DER  
  183.                 //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");  
  184.                 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);  
  185.                 curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);  
  186.   
  187.                 //服务端需要认证客户端的真实性,即双向认证。  
  188.                 if(pClientCalPath!=NULL)  
  189.                 {  
  190.                     curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);  
  191.                     curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);  
  192.                     curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");  
  193.                     curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);  
  194.                     curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);  
  195.                     curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");  
  196.                 }  
  197.             }              
  198.             //  
  199.             curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);  
  200.             curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
  201.   
  202.             //Web服务器一般会重定向链接,比如访问http:/xxx/x1.do自动转到http:/xxx/x2.do  
  203.             //所以一定要设置CURLOPT_FOLLOWLOCATION为1,否则重定向后的数据不会返回。  
  204.             curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);  
  205.   
  206.             res = curl_easy_perform(curl);  
  207.             curl_easy_cleanup(curl);  
  208.             return res;  
  209.         }  
  210.   
  211.   
  212.         int CHttpClient::MultipartFormdata(const char *pUrl,  
  213.                               const std::map<std::string,std::string> & mapFields,  
  214.                               const std::map<std::string,std::vector<std::string>> & mapFiles,  
  215.                               std::string & strResponse,  
  216.                               const char *pCookie,const char * pCaPath,  
  217.                               const char * pClientCalPath,const char * pClientCalPassword)  
  218.         {  
  219.             CURL *curl;  
  220.             CURLcode res;  
  221.   
  222.             curl = curl_easy_init();  
  223.             strResponse ="";  
  224.   
  225.             curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_MultipartFormdata);//write_data  
  226.             curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);  
  227.   
  228.             struct curl_httppost *formpost = 0;  
  229.             struct curl_httppost *lastptr  = 0;  
  230.   
  231.             //  
  232.             std::map<std::string,std::string>::const_iterator iterFields = mapFields.begin();  
  233.             while(iterFields!=mapFields.end())  
  234.             {  
  235.                 //curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,"data",CURLFORM_COPYCONTENTS, pData,CURLFORM_END);  
  236.                 curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,iterFields->first.c_str(),  
  237.                              CURLFORM_COPYCONTENTS, iterFields->second.c_str(),CURLFORM_END);  
  238.                 iterFields++;  
  239.             }  
  240.   
  241.             std::map<std::string,std::vector<std::string>>::const_iterator iterFiles = mapFiles.begin();  
  242.             while(iterFiles!=mapFiles.end())  
  243.             {  
  244.                 //"image/jpeg","image/png"  
  245.                 //curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME, "portraitFile", CURLFORM_FILE, pImageFileName,CURLFORM_CONTENTTYPE, "image/png", CURLFORM_END);  
  246.                 curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME,  
  247.                              iterFiles->first.c_str(), CURLFORM_FILE,  
  248.                              iterFiles->second[0].c_str(),CURLFORM_CONTENTTYPE,  
  249.                              iterFiles->second[1].c_str(), CURLFORM_END);  
  250.                 iterFiles++;  
  251.             }  
  252.   
  253.   
  254.             //  
  255.             curl_easy_setopt(curl, CURLOPT_URL, pUrl);  
  256.             curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);  
  257.   
  258.             if (pCookie!=0)  
  259.             {  
  260.                 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);  
  261.                 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);  
  262.             }  
  263.   
  264.             //单向认证用  
  265.             if(pCaPath!=0)  
  266.             {  
  267.                 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);  
  268.                 curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);  
  269.             }  
  270.   
  271.             //服务端需要认证客户端的真实性,即双向认证。  
  272.             if(pClientCalPath!=0 && pClientCalPassword!=0)  
  273.             {  
  274.                 curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);  
  275.                 curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);  
  276.                 curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");  
  277.                 curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);  
  278.                 curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);  
  279.                 curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");  
  280.             }  
  281.   
  282.             res = curl_easy_perform(curl);  
  283.             curl_easy_cleanup(curl);  
  284.   
  285.             curl_formfree(formpost);  
  286.             return res;  
  287.         }  
  288.   
  289.         int CHttpClient::GetFile(const char* pUrl,  
  290.                     const char* pLocalFullPath,  
  291.                     const char* pCookie,  
  292.                     const char* pCaPath,  
  293.                     const char* pClientCalPath,  
  294.                     const char* pClientCalPassword)  
  295.         {  
  296.             CURL *curl = NULL;  
  297.             CURLcode code;  
  298.             char bufError[CURL_ERROR_SIZE];  
  299.             std::string content;  
  300.             long retcode = 0;  
  301.   
  302.             code = curl_global_init(CURL_GLOBAL_DEFAULT);  
  303.             if (code != CURLE_OK)  
  304.             {  
  305.                 //printf("Failed to global init default [%d]\n", code);  
  306.                 return -100;  
  307.             }  
  308.   
  309.             curl = curl_easy_init();  
  310.             if (curl == NULL)  
  311.             {  
  312.                 //printf("Failed to create CURL connection\n");  
  313.                 return -200;  
  314.             }  
  315.             code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bufError);  
  316.             if (code != CURLE_OK)  
  317.             {  
  318.                 //printf("Failed to set error buffer [%d]\n", code);  
  319.                 return code;  
  320.             }  
  321.             //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);  
  322.             code = curl_easy_setopt(curl, CURLOPT_URL, pUrl);  
  323.             if (code != CURLE_OK)  
  324.             {  
  325.                 //printf("Failed to set URL [%s]\n", error);  
  326.                 goto _END;  
  327.             }  
  328.             code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  
  329.             if (code != CURLE_OK)  
  330.             {  
  331.                 //printf("Failed to set redirect option [%s]\n", error);  
  332.                 goto _END;  
  333.             }  
  334.             code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_GetFile);  
  335.             if (code != CURLE_OK)  
  336.             {  
  337.                 //printf("Failed to set writer [%s]\n", error);  
  338.                 goto _END;  
  339.             }  
  340.             code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);  
  341.             if (code != CURLE_OK)  
  342.             {  
  343.                 //printf("Failed to set write data [%s]\n", error);  
  344.                 goto _END;  
  345.             }  
  346.   
  347.             if (pCookie!=0)  
  348.             {  
  349.                 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);  
  350.                 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);  
  351.             }  
  352.   
  353.             //单向认证用  
  354.             if(pCaPath!=0)  
  355.             {  
  356.                 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);  
  357.                 curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);  
  358.             }  
  359.   
  360.             //服务端需要认证客户端的真实性,即双向认证。  
  361.             if(pClientCalPath!=0 && pClientCalPassword!=0)  
  362.             {  
  363.                 curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);  
  364.                 curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);  
  365.                 curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");  
  366.                 curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);  
  367.                 curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);  
  368.                 curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");  
  369.             }  
  370.   
  371.             code = curl_easy_perform(curl);  
  372.             if (code != CURLE_OK)  
  373.             {  
  374.                 //printf("Failed to get '%s' [%s]\n", URL, error);  
  375.                 goto _END;  
  376.             }  
  377.   
  378.             code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &retcode);  
  379.             if ((code == CURLE_OK) && retcode == 200)  
  380.             {  
  381.                 double length = 0;  
  382.                 code = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length);  
  383.                 //printf("%d", retcode);  
  384.                 FILE * file = fopen(pLocalFullPath, "wb");  
  385.                 fseek(file, 0, SEEK_SET);  
  386.                 fwrite(content.c_str(), 1, (size_t)length, file);  
  387.                 fclose(file);  
  388.   
  389.                 code =  CURLE_OK;  
  390.                 goto _END;  
  391.             }  
  392.         _END:  
  393.             curl_easy_cleanup(curl);  
  394.   
  395.             return code;  
  396.         }  
  397.   
  398.         ///////////////////////////////////////////////////////////////////////////////////////////////  
  399.         void CHttpClient::SetDebug(bool bDebug)  
  400.         {  
  401.             m_bDebug = bDebug;  
  402.         }  
  403.   
  404.         void Init()  
  405.         {  
  406.             //the function is not thread safe.  
  407.             curl_global_init(CURL_GLOBAL_ALL);  
  408.         }  
  409.   
  410.         void Cleanup()  
  411.         {  
  412.             curl_global_cleanup();  
  413.         }  
  414.     }  
  415. }  

注意:

[1]MSys64 Mingw32 QtCreator 32位C++程序 配置libcurl
假设Msys64是安装在C盘默认路径上
第一步:在Msys64中查询可用的curl包
pacman -Ss curl


第二步:安装
pacman -S mingw-w64-i686-curl


第三步:在.pro文件下加入下面的代码
LIBS += C:\msys64\mingw32\lib\libcurl.dll.a
INCLUDEPATH += C:\msys64\mingw32\include
最后:编译链接依赖libcurl的项目成功。


[2]如何产生cer文件

https原理及tomcat配置https方法
http://jingyan.baidu.com/article/a948d6515d3e850a2dcd2ee6.html


[3]单向认证,让客户端信任服务端证书

第一步:
双击从服务端keystore中导出的cer文件可以导入证书。
windows下“certmgr.msc”命令可以进入证书管理。
自己制作的证书导入到Win7后默认在“中级证书颁发机构”->“证书”节点里。


第二步:
需要把你做的证书拖到“受信任的根证书颁发机构”->“证书”节点中去,否则
浏览器会提醒“此网站出具的安全证书不是由受信任的证书颁发机构颁发的”等类似错误。
chrome需要重启,IE直接刷新页面,就不会出现警告了。


注意:
数字证书转换cer---pem 
在Msys2 Shell中确保安装好openssl.
在Msys2 Shell中使用openssl命令后进入openssl提示符,输入下面的命令
x509 -inform der -in d:/MyServerSecurity/tomcat7.cer -out d:/MyServerSecurity/tomcat7.pem


[4]双向认证,让服务端信任客户端的证书

相当于“Https单向认证”,添加了“服务端验证客户端身份真实性”的动作。
需要注意的是:服务端的密钥库参数“CN”必须与服务端的IP地址相同,否则会报错,客户端的任意。
如果服务端的CN为lijun,则客户端不能为lijun,即这两个不能是同一个名字。


第一步:客户端生成证书(用于服务端验证客户端)
keytool -validity 365 -genkeypair -v -alias kagula -keyalg RSA -storetype PKCS12 -keystore D:\MyClientSecurity\kagulakey.p12 -storepass 123456 -keypass 123456
kagula为证书的名称,D:\MyClientSecurity\kagulakey.p12证书的存放位置。


第二步:证书格式转为cer文件。
keytool -export -v -alias kagula -keystore D:\MyClientSecurity\kagulakey.p12 -storetype PKCS12 -storepass 123456 -rfc -file D:\MyClientSecurity\kagulakey.cer
kagula为证书的名称,D:\MyClientSecurity\kagulakey.p12证书的存放位置,123456证书密码,D:\MyClientSecurity\kagulakey.cer导出的文件。


第三步:添加到(或新建)一个keystore文件
keytool -import -v -alias kagula -file D:\MyClientSecurity\kagulakey.cer -keystore D:\MyServerSecurity\tomcat7_client.keystore -storepass 123456
tomcat7_client.keystore如果不存在就会新建一个keystore,如果存在会添加到已经存在的keystore中。


第四步:查看keystore文件中的内容
keytool -list -keystore D:\MyServerSecurity\tomcat7_client.keystore


第五步:修改tomcat7中的server.xml文件
原单向认证的配置如下
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="D:\\MyServerSecurity\\tomcat7.keystore" keystorePass="123456"/>
               
               
现在修改后,如下
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS"
               keystoreFile="D:\\MyServerSecurity\\tomcat7.keystore" keystorePass="123456"
  truststoreFile="D:\\MyServerSecurity\\tomcat7_client.keystore" truststorePass="123456"/>           
添加了最后一行属性使它指向客户端证书,并把clientAuth属性从false改为true。


第六步(可选):
Step6-1:
测试Windows下的Chrome是否还能访问服务器,果然刷新浏览器后
“https://lijun:8443/escortcashbox/main/aboutUs.do”返回错误信息
Step6-2:
测试libcurl是否还能访问服务器,现在libcurl返回7(无法连接服务器)的错误信息。


最后一步-让Windows下的Chrome和IE能访问服务端:
双击D:\MyClientSecurity\kagulakey.p12文件,“不需要添加到受信任的根证书机构”结点,直接导入证书即可。
默认在certmgr.msc命令,“个人”->“证书”节点下。


最后一步-让libcurl能访问服务端:
使用msys64打开openssl命令行工具
#客户端个人证书的公钥
openssl>pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_publickey.pem -nokeys
也许如果在当前command shell下能找到openssl.exe也可以用下面的命令
“openssl pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_publickey.pem -nokeys”


#客户端个人证书的私钥
openssl pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_privatekey.pem -nocerts -nodes


#也可以转换为公钥与私钥合二为一的文件;     客户端公钥与私钥,一起存在all.pem中
openssl>pkcs12 -in D:\MyClientSecurity\kagulakey.p12 -out D:\MyClientSecurity\client_all.pem -nodes




1、使用client_publickey.pem + client_privatekey.pem  (未在win console shell下测试)
curl -k --cert client_publickey.pem --key D:\MyClientSecurity\client_privatekey.pem https://lijun:8443/escortcashbox/main/aboutUs.do


2、可以在Msys64 Shell中执行curl命令(如果已经安装了curl)...使用all.pem
curl -k --cert /d/MyClientSecurity/client_all.pem https://lijun:8443/escortcashbox/main/aboutUs.do


下面是双向认证的参考资料
SSL——Secure Sockets Layer
http://www.blogjava.net/icewee/archive/2012/06/04/379947.html

补充阅读资料

使用libcurl实现上传文件到FTP服务器

http://blog.youkuaiyun.com/lee353086/article/details/5823145

 

使用libcurl下载http://www.baidu.com/img/baidu.gif示例

http://www.cppblog.com/qiujian5628/archive/2008/06/28/54873.html

 

libcurl的使用总结(一)

http://www.vimer.cn/2010/03/libcurl%E7%9A%84%E4%BD%BF%E7%94%A8%E6%80%BB%E7%BB%93%EF%BC%88%E4%B8%80%EF%BC%89.html

 

PHP的curl实现get,post 和 cookie

http://www.tsingpost.com/articles/201403/525.html


文章来源:

http://blog.youkuaiyun.com/lee353086/article/details/40349761

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值