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

来源:互联网 发布:查看linux开机启动项 编辑:程序博客网 时间:2024/06/08 08:40

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客户端示例


如何使用

#include <iostream>#include <string>using namespace std;#include "httpclient.h"int main(int argc, char *argv[]){    string response;    //login    kagula::network::CHttpClient client;    int nR = client.Post("https://lijun:8443/escortcashbox/main/login.do",                         "data={\"version\":\"1.0.0.0\",\"user\":\"admin\",\"password\":\"123\"}",                                                  response,true,                         "d:\cookie.txt",                         "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem",                         "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem",                         "123456");    cout << nR << endl <<response << endl;    //upload png file    /*    std::map<std::string,std::string> mapFields;    std::map<std::string,std::vector<std::string>> mapFiles;    mapFields["data"] = "{\"version\":\"1.0.0.0\",\"socialid\":\"1012\",\"realname\":\"realnamevalue\",\"portrait\":\"protraitvalue\",\"fingerid\":\"fingeridvalue\",\"groupid\":\"123\"}";    std::vector<std::string> vecFile(2);    vecFile[0] = "d:\\b.png";    vecFile[1] = "image/png";    mapFiles["portraitFile"] = vecFile;    nR = client.MultipartFormdata("https://lijun:8443/escortcashbox/main/escortStaffAdd.do",                                  mapFields,mapFiles,                                  response,                                  "d:\cookie.txt",                                  "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem",                                  "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem",                                  "123456");    cout << nR << endl << response << endl;*/    //download png file    nR = client.GetFile("https://lijun:8443/escortcashbox/upload/img/20160527_110514_679_426.png",                        "d:/ee.png",                        "d:\cookie.txt",                        "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem",                        "D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem",                        "123456");    cout << nR << endl;    return 0;}


HttpClient.h封装好的头文件

//HttpClient.h源代码清单#ifndef _HTTPCLIENT_H_#define _HTTPCLIENT_H_#include <string>#include <map>#include <vector>/*Title: Get Response from Web Server by HTTP/HTTPS method.Environment:Windows 7SP1, Windows 8.1, Windows 10QT Creator 3.5.1, Visual Studio 2013 Update1, Visual Studio 2013 Update5libcurl 7.36.0, libcurl 7.46.0, Qt 5.6, MSYS2 64bits gcc 5.3.0Last Update: 2016-05-27Remark:[1]如果要在多线程方式下同时调用多个CHttpClient实例, 需要在App初始化的时候调用kagula::network::Init(); 在App结束的时候调用kagula::network::Cleanup();[2]编译libcurl必须打开zlib标志,并且把OpenSSL也链进去。Reference:curl_eay_setopt manualhttp://www.helplib.net/s/linux.die/65_2740/man-3-curl-easy-setopt.shtmlC++ cout formathttp://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html*/namespace kagula{    namespace network    {        void Init();        void Cleanup();        class CHttpClient        {        public:            CHttpClient(void);            ~CHttpClient(void);        public:            /**            * @brief HTTP/HTTPS POST/GET请求            * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com            * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…            * @param strCookie 输入参数,Cookie文件名,例如 d:\temp\cookie.txt            *                          如果为空,不启用Cookie.            * @param strResponse 输出参数,返回的内容            * @param bPost 是否Post方式发送请求,默认Post方式发送请求。            * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.            * @param pClientCalPath 输入参数,为客户端证书的路径.如果输入为NULL,则不验证客户端证书的有效性.            * @param pClientCalPassword 输入参数,为客户端证书的存取密码.            * @return 返回是否Post成功            * 0  成功            * 7  无法连接            * 28 超时            * 58 服务端验证客户端证书失败。            * 60 客户端验证服务端证书失败。            */            int Post(const char* pUrl,                     const char* pPost,                     std::string &strResponse,                     bool bPost,                     const char* pCookie,                     const char* pCaPath = NULL,                     const char* pClientCalPath = NULL,                     const char* pClientCalPassword = NULL);            int MultipartFormdata(const char *pUrl,                                  const std::map<std::string,std::string> & mapFields,                                  const std::map<std::string,std::vector<std::string>> & mapFiles,                                  std::string & strResponse,                                  const char *pCookie,                                  const char * pCaPath = NULL,                                  const char * pClientCalPath = NULL,                                  const char * pClientCalPassword = NULL);            int GetFile(const char* pUrl,                        const char* pLocalFullPath,                        const char* pCookie,                        const char* pCaPath = NULL,                        const char* pClientCalPath = NULL,                        const char* pClientCalPassword = NULL);        public:            void SetDebug(bool bDebug);            std::string getMsgInChinese(int code);        private:            bool m_bDebug;            bool PrintCookies(void* curl, std::string& strOut);        };    }}#endif


源文件清单

//HttpClient.cpp源代码清单#include "HttpClient.h"#include <iostream>#include <curl/curl.h>#include <iomanip>#include <sstream>#ifdef WIN32#pragma comment(lib,"libcurl_imp.lib")#endifnamespace kagula{    namespace network    {        CHttpClient::CHttpClient(void) :            m_bDebug(false)        {        }        CHttpClient::~CHttpClient(void)        {        }        bool CHttpClient::PrintCookies(void* curl, std::string& strOut)        {            std::ostringstream ostr;            CURLcode res;            struct curl_slist *cookies;            res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);            if (res != CURLE_OK) {                ostr << "Curl curl_easy_getinfo failed:" << curl_easy_strerror(res) << std::endl;                strOut = ostr.str();                return false;            }            const struct curl_slist *nc = cookies;            int i = 1;            ostr << "Cookies, curl knows:" << std::endl;            while (nc) {                ostr << "[" << i++ << "]: " << nc->data << std::endl;                nc = nc->next;            }            return true;        }        static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)        {            if (itype == CURLINFO_TEXT)            {                //printf("[TEXT]%s\n", pData);            }            else if (itype == CURLINFO_HEADER_IN)            {                printf("[HEADER_IN]%s\n", pData);            }            else if (itype == CURLINFO_HEADER_OUT)            {                printf("[HEADER_OUT]%s\n", pData);            }            else if (itype == CURLINFO_DATA_IN)            {                printf("[DATA_IN]%s\n", pData);            }            else if (itype == CURLINFO_DATA_OUT)            {                printf("[DATA_OUT]%s\n", pData);            }            return 0;        }        size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid)        {            std::string* str = reinterpret_cast<std::string*>(lpVoid);            if (NULL == str || NULL == buffer)            {                return -1;            }            char* pData = reinterpret_cast<char*>(buffer);            str->append(pData, size * nmemb);            return nmemb;        }        size_t OnWriteData_MultipartFormdata( void *inBuffer, size_t size, size_t nmemb, void *outBuffer )        {            int len = size * nmemb;            char *temp = new char[len+1];            memcpy(temp,inBuffer,len);            temp[len]=0;            reinterpret_cast<std::string *>(outBuffer)->append(temp);            delete temp;            return len;        }        size_t OnWriteData_GetFile(void *inBuffer, int size, int nmemb, std::string &content)        {            long len = size * nmemb;            std::string temp((char *)inBuffer, len);            content += temp;            return len;        }        std::string CHttpClient::getMsgInChinese(int code)        {            switch(code)            {            case 0:                return "通讯成功";            case 7:                return "服务器连接失败。";            case 28:                return "连接超时。";            case 58:                return "服务端验证客户端证书失败。";            case 60:                return "客户端验证服务端证书失败。";            default:                return "";            }        }        int CHttpClient::Post(const char* pUrl,                              const char* pPost,                              std::string & strResponse,                              bool bPost,                              const char* pCookie,                              const char* pCaPath,                              const char* pClientCalPath,                              const char* pClientCalPassword)        {            strResponse = "";            CURLcode res;            CURL* curl = curl_easy_init();            if (NULL == curl)            {                return CURLE_FAILED_INIT;            }            if (m_bDebug)            {                curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);                curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);            }            curl_easy_setopt(curl, CURLOPT_URL, pUrl);            if(bPost)            {                curl_easy_setopt(curl, CURLOPT_POST, 1);                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pPost);            }            curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post);            curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);            curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);            if (pCookie!=0)            {                curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);                curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);            }            if (NULL == pCaPath)            {                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);                //需要在编译curl的时候,一同编译zlib标志。要不然找不到这个标志.                //当然前提是你已经编译完成zlib.                //发出接受gzip压缩内容的请求,如果服务器支持gzip内容,会返回压缩后的数据。                //如果Http服务器不支持gzip encoding也不影响libcurl正常工作。                //接受数据的时候,如果返回的是压缩数据,libcurl会自动解压数据。                curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");            }            else            {                //缺省情况就是PEM,所以无需设置,另外支持DER                //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);                curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);                //服务端需要认证客户端的真实性,即双向认证。                if(pClientCalPath!=NULL)                {                    curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);                    curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);                    curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");                    curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);                    curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);                    curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");                }            }                        //            curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);            curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);            //Web服务器一般会重定向链接,比如访问http:/xxx/x1.do自动转到http:/xxx/x2.do            //所以一定要设置CURLOPT_FOLLOWLOCATION为1,否则重定向后的数据不会返回。            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);            res = curl_easy_perform(curl);            curl_easy_cleanup(curl);            return res;        }        int CHttpClient::MultipartFormdata(const char *pUrl,                              const std::map<std::string,std::string> & mapFields,                              const std::map<std::string,std::vector<std::string>> & mapFiles,                              std::string & strResponse,                              const char *pCookie,const char * pCaPath,                              const char * pClientCalPath,const char * pClientCalPassword)        {            CURL *curl;            CURLcode res;            curl = curl_easy_init();            strResponse ="";            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_MultipartFormdata);//write_data            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);            struct curl_httppost *formpost = 0;            struct curl_httppost *lastptr  = 0;            //            std::map<std::string,std::string>::const_iterator iterFields = mapFields.begin();            while(iterFields!=mapFields.end())            {                //curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,"data",CURLFORM_COPYCONTENTS, pData,CURLFORM_END);                curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,iterFields->first.c_str(),                             CURLFORM_COPYCONTENTS, iterFields->second.c_str(),CURLFORM_END);                iterFields++;            }            std::map<std::string,std::vector<std::string>>::const_iterator iterFiles = mapFiles.begin();            while(iterFiles!=mapFiles.end())            {                //"image/jpeg","image/png"                //curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME, "portraitFile", CURLFORM_FILE, pImageFileName,CURLFORM_CONTENTTYPE, "image/png", CURLFORM_END);                curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME,                             iterFiles->first.c_str(), CURLFORM_FILE,                             iterFiles->second[0].c_str(),CURLFORM_CONTENTTYPE,                             iterFiles->second[1].c_str(), CURLFORM_END);                iterFiles++;            }            //            curl_easy_setopt(curl, CURLOPT_URL, pUrl);            curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);            if (pCookie!=0)            {                curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);                curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);            }            //单向认证用            if(pCaPath!=0)            {                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);                curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);            }            //服务端需要认证客户端的真实性,即双向认证。            if(pClientCalPath!=0 && pClientCalPassword!=0)            {                curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);                curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);                curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");                curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);                curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);                curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");            }            res = curl_easy_perform(curl);            curl_easy_cleanup(curl);            curl_formfree(formpost);            return res;        }        int CHttpClient::GetFile(const char* pUrl,                    const char* pLocalFullPath,                    const char* pCookie,                    const char* pCaPath,                    const char* pClientCalPath,                    const char* pClientCalPassword)        {            CURL *curl = NULL;            CURLcode code;            char bufError[CURL_ERROR_SIZE];            std::string content;            long retcode = 0;            code = curl_global_init(CURL_GLOBAL_DEFAULT);            if (code != CURLE_OK)            {                //printf("Failed to global init default [%d]\n", code);                return -100;            }            curl = curl_easy_init();            if (curl == NULL)            {                //printf("Failed to create CURL connection\n");                return -200;            }            code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bufError);            if (code != CURLE_OK)            {                //printf("Failed to set error buffer [%d]\n", code);                return code;            }            //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);            code = curl_easy_setopt(curl, CURLOPT_URL, pUrl);            if (code != CURLE_OK)            {                //printf("Failed to set URL [%s]\n", error);                goto _END;            }            code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);            if (code != CURLE_OK)            {                //printf("Failed to set redirect option [%s]\n", error);                goto _END;            }            code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_GetFile);            if (code != CURLE_OK)            {                //printf("Failed to set writer [%s]\n", error);                goto _END;            }            code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);            if (code != CURLE_OK)            {                //printf("Failed to set write data [%s]\n", error);                goto _END;            }            if (pCookie!=0)            {                curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);                curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);            }            //单向认证用            if(pCaPath!=0)            {                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);                curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);            }            //服务端需要认证客户端的真实性,即双向认证。            if(pClientCalPath!=0 && pClientCalPassword!=0)            {                curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);                curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);                curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");                curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);                curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);                curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");            }            code = curl_easy_perform(curl);            if (code != CURLE_OK)            {                //printf("Failed to get '%s' [%s]\n", URL, error);                goto _END;            }            code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &retcode);            if ((code == CURLE_OK) && retcode == 200)            {                double length = 0;                code = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length);                //printf("%d", retcode);                FILE * file = fopen(pLocalFullPath, "wb");                fseek(file, 0, SEEK_SET);                fwrite(content.c_str(), 1, (size_t)length, file);                fclose(file);                code =  CURLE_OK;                goto _END;            }        _END:            curl_easy_cleanup(curl);            return code;        }        ///////////////////////////////////////////////////////////////////////////////////////////////        void CHttpClient::SetDebug(bool bDebug)        {            m_bDebug = bDebug;        }        void Init()        {            //the function is not thread safe.            curl_global_init(CURL_GLOBAL_ALL);        }        void Cleanup()        {            curl_global_cleanup();        }    }}

注意:

[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.csdn.net/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

0 0