linux c++ curl https 請求並雙向驗證SSL證書

一、配置curl https請求須要提供 CA證書、客戶端證書和客戶端祕鑰,這三個文件的pem格式。html

  分別對應 curl_easy_setopt() 函數的 下面三個參數:ios

  CURLOPT_CAINFO - path to Certificate Authority (CA) bundle
  CURLOPT_SSLKEY - specify private keyfile for TLS and SSL client cert
  CURLOPT_SSLCERT - set SSL client certificatejson

通常建立SSL證書時會生成 ca.crt , client.crt, client.key, server.crt, server.key 等,而 curl客戶端請求,只須要將 ca.crt , client.crt, client.key轉成相應的 pem格式 使用。轉換方法以下:segmentfault

  1)將 CRT 轉成 PEM---
    不能直接將 .crt 轉成 .pem,須要通過 .der 中轉windows

   openssl x509 -in client.crt -out client.der -outform der
   openssl x509 -in client.der -inform der -outform pem -out client.pem

   openssl x509 -in ca.crt -out ca.der -outform der
   openssl x509 -in ca.der -inform der -outform pem -out ca_info.pem

  2)將 .key 轉成 .pem服務器

    不能直接將 .key 轉成 .pem,須要通過 .der 中轉    app

   openssl rsa -in client.key -out client.der -outform DER
    openssl rsa -inform DER -outform PEM -in client.der -out client_key.pem

二、配置 curl https請求curl

  1) 官方例程以下:
  curl 接口文檔說明:
   https://curl.haxx.se/libcurl/c/curl_easy_setopt.html
   https://curl.haxx.se/libcurl/c/CURLOPT_CAINFO.html
      https://curl.haxx.se/libcurl/c/https.html函數

  CURLOPT_CAINFO - path to Certificate Authority (CA) bundle
  CURLOPT_SSLKEY - specify private keyfile for TLS and SSL client cert
  CURLOPT_SSLCERT - set SSL client certificatethis

按下面代碼部分進行配置,便可訪問

    CURL *curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");

      // 下面兩個爲驗證對方和驗證主機名,若爲0,則跳過驗證,我這個服務器必須驗證才能獲得請求數據
      curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L); 
      curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 1L);    
    
        // 配置 https 請求所需證書
      curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/certs/cabundle.pem");
      curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
      curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
      curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");

      ret = curl_easy_perform(curl);
      curl_easy_cleanup(curl);
  }     

  2)個人代碼以下

  這是一個完整的 curl 發送 https get 請求,並帶中文參數  

#include <iostream>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <curl/curl.h>
#include <exception>
#include <string>
#include <iostream>
#include <stdlib.h>

int writer(char *data, size_t size, size_t nmemb, string *writerData)
{
  unsigned long sizes = size * nmemb;
  if (writerData == NULL)
  return -1;

  writerData->append(data, sizes);
  return sizes;
}

string parseJsonResponse_question(string input)
{
    Json::Value root;
    Json::Reader reader;
    bool parsingSuccessful = reader.parse(input, root);
    if(!parsingSuccessful)
    {
        std::cout<<"!!! Failed to parse the response data"<< std::endl;
        return "";
    }
    const Json::Value text = root["obj"]["question"];
    string result = text.asString(); 
    return result;
}

string HttpsGetRequest_question(string input)
{
    string buffer, ling_result;

    // 對請求參數中的中文和特殊字符(如空格等)進行處理,方可以使用
    char * escape_control = curl_escape(input.c_str(), input.size());
    input = escape_control;
    curl_free(escape_control);

    string str_url= "https://*.*.*.*/question?question=" + input; // alter *.*.*.* by your server address
    
    try
    {
        CURL *pCurl = NULL;
        CURLcode res;

        // In windows, this will init the winsock stuff
        curl_global_init(CURL_GLOBAL_ALL); 
        // get a curl handle
        pCurl = curl_easy_init();
        if (NULL != pCurl)
        {
            // 設置超時時間爲8秒
            curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 8); 
            curl_easy_setopt(pCurl, CURLOPT_URL, str_url.c_str());

            // 下面兩個爲驗證對方和驗證主機名,若爲0,則跳過驗證,我這個服務器必須驗證才能獲得請求數據
            curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L); 
            curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 1L);

            // 配置 https 請求所需證書
            curl_easy_setopt(pCurl,CURLOPT_CAINFO,"/etc/msc/ca_info.pem"); 
            curl_easy_setopt(pCurl, CURLOPT_SSLCERT, "/etc/msc/client.pem");
            curl_easy_setopt(pCurl, CURLOPT_SSLKEY, "/etc/msc/client_key.pem");
            curl_easy_setopt(pCurl, CURLOPT_KEYPASSWD, "your_key_password");

            curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, writer); 
            curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &buffer);

            // Perform the request, res will get the return code
            res = curl_easy_perform(pCurl);
            // Check for errors
            if (res != CURLE_OK)
            {
                printf("curl_easy_perform() failed:%s\n", curl_easy_strerror(res));
            }
            curl_easy_cleanup(pCurl);
        }
        curl_global_cleanup();
    }
    catch (std::exception &ex)
    {
        printf("curl exception %s.\n", ex.what());
    }
    if(buffer.empty())
    {
        std::cout<< "!!! ERROR The sever response NULL" << std::endl;
    }
    else
    {
        ling_result = parseJsonResponse_question(buffer);
    }
    return ling_result;
}

參考:

  http://blog.csdn.net/rztyfx/article/details/6919220  https://segmentfault.com/a/1190000011709784

相關文章
相關標籤/搜索