zoukankan      html  css  js  c++  java
  • linux c++ curl https 请求并双向验证SSL证书

    1、配置curl https请求需要提供 CA证书、客户端证书和客户端秘钥,这三个文件的pem格式。

      分别对应 curl_easy_setopt() 函数的 下面三个参数:

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

    一般创建SSL证书时会生成 ca.crt , client.crt, client.key, server.crt, server.key 等,而 curl客户端请求,只需要将 ca.crt , client.crt, client.key转成相应的 pem格式 使用。转换方法如下:

      1)将 CRT 转成 PEM---
        不能直接将 .crt 转成 .pem,需要经过 .der 中转

       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 中转    

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

    2、配置 curl https请求

      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 certificate

    按下面代码部分进行配置,即可访问

        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
    ", curl_easy_strerror(res));
                }
                curl_easy_cleanup(pCurl);
            }
            curl_global_cleanup();
        }
        catch (std::exception &ex)
        {
            printf("curl exception %s.
    ", 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

  • 相关阅读:
    Three.js 类的粗略总结和实现
    JavaScript方法
    JavaScript 继承和数组
    JavaScript 函数
    操作系统之堆和栈的区别
    第十二章 动态内存
    第十三章-第六小节-对象移动
    第十五章 面形对象程序设计
    动态建树和静态建树
    高斯消元整数版和浮点数版实现
  • 原文地址:https://www.cnblogs.com/yongpan/p/8084854.html
Copyright © 2011-2022 走看看