Libcurl的編譯_HTTP/HTTPSclient源代碼演示樣例

HTTP/HTTPSclient源代碼演示樣例

環境:  zlib-1.2.8  openssl-1.0.1g  curl-7.36html

Author:  Kagulajava

LastUpdateDate: 2016-05-09node

閱讀前提:CMake工具的基本使用、配置openssl-1.0.1g 開發環境linux

 

編譯zlib庫

         下載zlib-1.2.8.tar.gz並解壓縮到" D:\SDK\zlib-1.2.8",使用CMake工具生成zlib.sln。在Visual Studio2013中打開並編譯就能夠。ios

編譯curl-7.36.0

    若是Open SSL已經安裝到「D:\SDK\openssl-1.0.1g」,先設置如下的環境變量chrome

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

OPENSSL_ROOT_DIR=D:\SDK\openssl-1.0.1gapache

    從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文件後打開,爲裏面的curlproject項目加入「USE_MANUAL」宏定義,而後build裏面的4個項目成功。vim

   爲項目加入連接庫libcurl_imp.lib  , 把libcurl.dll文件拷貝到C++項目路徑下,不然程序執行會提示找不到動態連接庫。windows

如下是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:\temp\cookie.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\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 "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]\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); } //服務端需要認證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]\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]單向認證。讓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:\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證書password,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是否還能訪問server,果真刷新瀏覽器後
「https://lijun:8443/escortcashbox/main/aboutUs.do」返回錯誤信息
Step6-2:
測試libcurl是否還能訪問server。現在libcurl返回7(沒法鏈接server)的錯誤信息。


最後一步-讓Windows下的Chrome和IE能訪問服務端:
雙擊D:\MyClientSecurity\kagulakey.p12文件,「不需要加入到受信任的根證書機構」結點。直接導入證書就能夠。
默認在certmgr.msc命令,「我的」->「證書」節點下。


最後一步-讓libcurl能訪問服務端:
使用msys64打開openssl命令行工具
#client我的證書的公鑰
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」


#client我的證書的私鑰
openssl pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_privatekey.pem -nocerts -nodes


#也可以轉換爲公鑰與私鑰合二爲一的文件;     client公鑰與私鑰,一塊兒存在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


二、可以在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

相關文章
相關標籤/搜索