zoukankan      html  css  js  c++  java
  • Libcurl的编译_HTTP/HTTPSclient源代码演示样例

    HTTP/HTTPSclient源代码演示样例

    环境:  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:SDKzlib-1.2.8",使用CMake工具生成zlib.sln。在Visual Studio2013中打开并编译就可以。

    编译curl-7.36.0

        如果Open SSL已经安装到“D:SDKopenssl-1.0.1g”,先设置以下的环境变量

    OPENSSL_LIBRARIES=D:SDKopenssl-1.0.1gout32

    OPENSSL_ROOT_DIR=D:SDKopenssl-1.0.1g

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

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

    以下是HTTP/HTTPSclient演示样例


    怎样使用

    #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 10
    QT Creator 3.5.1, Visual Studio 2013 Update1, Visual Studio 2013 Update5
    libcurl 7.36.0, libcurl 7.46.0, Qt 5.6, MSYS2 64bits gcc 5.3.0
    Last Update: 2016-05-27
    Remark:
    [1]假设要在多线程方式下同一时候调用多个CHttpClient实例。
     须要在App初始化的时候调用kagula::network::Init();
     在App结束的时候调用kagula::network::Cleanup();
    [2]编译libcurl必须打开zlib标志。而且把OpenSSL也链进去。
    
    Reference:
    curl_eay_setopt manual
    http://www.helplib.net/s/linux.die/65_2740/man-3-curl-easy-setopt.shtml
    C++ cout format
    http://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:	empcookie.txt
                *                          假设为空,不启用Cookie.
                * @param strResponse 输出參数,返回的内容
                * @param bPost 是否Post方式发送请求,默认Post方式发送请求。
                * @param pCaPath 输入參数,为CA证书的路径.假设输入为NULL,则不验证server端证书的有效性.
                * @param pClientCalPath 输入參数,为client证书的路径.假设输入为NULL,则不验证client证书的有效性.
                * @param pClientCalPassword 输入參数,为client证书的存取password.
                * @return 返回是否Post成功
                * 0  成功
                * 7  无法连接
                * 28 超时
                * 58 服务端验证client证书失败。
                * 60 client验证服务端证书失败。
                */
                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")
    #endif
    
    namespace 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
    ", pData);
                }
                else if (itype == CURLINFO_HEADER_IN)
                {
                    printf("[HEADER_IN]%s
    ", pData);
                }
                else if (itype == CURLINFO_HEADER_OUT)
                {
                    printf("[HEADER_OUT]%s
    ", pData);
                }
                else if (itype == CURLINFO_DATA_IN)
                {
                    printf("[DATA_IN]%s
    ", pData);
                }
                else if (itype == CURLINFO_DATA_OUT)
                {
                    printf("[DATA_OUT]%s
    ", 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 "server连接失败。";
                case 28:
                    return "连接超时。";
                case 58:
                    return "服务端验证client证书失败。";
                case 60:
                    return "client验证服务端证书失败。

    "; 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压缩内容的请求,假设server支持gzip内容,会返回压缩后的数据。 //假设Httpserver不支持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); //服务端须要认证client的真实性,即双向认证。 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); //Webserver通常会重定向链接。比方訪问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); } //服务端须要认证client的真实性。即双向认证。 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] ", code); return -100; } curl = curl_easy_init(); if (curl == NULL) { //printf("Failed to create CURL connection "); return -200; } code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bufError); if (code != CURLE_OK) { //printf("Failed to set error buffer [%d] ", 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] ", error); goto _END; } code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); if (code != CURLE_OK) { //printf("Failed to set redirect option [%s] ", error); goto _END; } code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_GetFile); if (code != CURLE_OK) { //printf("Failed to set writer [%s] ", error); goto _END; } code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content); if (code != CURLE_OK) { //printf("Failed to set write data [%s] ", 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); } //服务端须要认证client的真实性。即双向认证。 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] ", 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:msys64mingw32liblibcurl.dll.a
    INCLUDEPATH += C:msys64mingw32include
    最后:编译链接依赖libcurl的项目成功。



    [2]怎样产生cer文件

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


    [3]单向认证。让client信任服务端证书

    第一步:
    双击从服务端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]双向认证。让服务端信任client的证书

    相当于“Https单向认证”,加入了“服务端验证client身份真实性”的动作。


    须要注意的是:服务端的密钥库參数“CN”必须与服务端的IP地址同样,否则会报错,client的随意。
    假设服务端的CN为lijun,则client不能为lijun。即这两个不能是同一个名字。


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


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


    第三步:加入到(或新建)一个keystore文件
    keytool -import -v -alias kagula -file D:MyClientSecuritykagulakey.cer -keystore D:MyServerSecurity omcat7_client.keystore -storepass 123456
    tomcat7_client.keystore假设不存在就会新建一个keystore,假设存在会加入到已经存在的keystore中。




    第四步:查看keystore文件里的内容
    keytool -list -keystore D:MyServerSecurity omcat7_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是否还能訪问server,果然刷新浏览器后
    “https://lijun:8443/escortcashbox/main/aboutUs.do”返回错误信息
    Step6-2:
    測试libcurl是否还能訪问server。如今libcurl返回7(无法连接server)的错误信息。


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


    最后一步-让libcurl能訪问服务端:
    使用msys64打开openssl命令行工具
    #client个人证书的公钥
    openssl>pkcs12 -in D:MyClientSecuritymyclientkey.p12 -out D:MyClientSecurityclient_publickey.pem -nokeys
    或许假设在当前command shell下能找到openssl.exe也能够用以下的命令
    “openssl pkcs12 -in D:MyClientSecuritymyclientkey.p12 -out D:MyClientSecurityclient_publickey.pem -nokeys”


    #client个人证书的私钥
    openssl pkcs12 -in D:MyClientSecuritymyclientkey.p12 -out D:MyClientSecurityclient_privatekey.pem -nocerts -nodes


    #也能够转换为公钥与私钥合二为一的文件;     client公钥与私钥,一起存在all.pem中
    openssl>pkcs12 -in D:MyClientSecuritykagulakey.p12 -out D:MyClientSecurityclient_all.pem -nodes




    1、使用client_publickey.pem + client_privatekey.pem  (未在win console shell下測试)
    curl -k --cert client_publickey.pem --key D:MyClientSecurityclient_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实现上传文件到FTPserver

    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

  • 相关阅读:
    基于 Javassist 和 Javaagent 实现动态切面
    基于SpringBoot搭建应用开发框架(二) —— 登录认证
    服务器集成环境搭建
    多租户个性化服务路由
    基于SpringBoot搭建应用开发框架(一) —— 基础架构
    Redis 学习(三) —— 事务、消息发布订阅
    Redis 学习(二) —— 数据类型及操作
    Redis 学习(一) —— 安装、通用key操作命令
    用FastDFS一步步搭建文件管理系统
    在Intellij IDEA中使用Debug
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6729710.html
Copyright © 2011-2022 走看看