2017-03-23 142 views
3

我正在嘗試使用cppnetlib,甚至是boost asio庫連接來執行簡單的url獲取並將結果頁向下拉。https客戶端與cpp-netlib使用客戶端證書和密碼獲取

我已經得到它與http協作,甚至https使用cppnetlib,但我需要提供一個客戶端certitifcate需要密碼.. Unforntuntley我需要使用舊的v0.10 cppnetlib。

這是可能的。我認爲答案是創建我自己的_io_service和custome爲具有證書和密碼的https請求進行配置,然後將其提供給boost :: network :: http:client構造函數。下面的工作在http中,並且可以在沒有證書要求的情況下用於https。

std::string url = "http://www.boost.org"; 
std::string certFile = "C:\\cert\\mycert.p12"; 
std::string password = "MyPassWord"; 
try { 
     http::client client; 
     http::client::request request(url); 
     http::client::response response = client->get(request); 

     std::string resultText = static_cast<std::string>(body(response)); 
     std::cout << resultText << std::endl; 
     delete client; 
    } 
    catch (std::exception &e) { 
     std::cerr << "Caught something connecting " << e.what() << std::endl; 
    } 
+0

的包括我也要除了使用ASIO直接用於HTTPS GET使用P12文件和密碼,客戶證書 – Jim

+0

事實證明,它不能做cppnetlib v0.10,我會接受使用標準PEM文件的解決方案,使用升壓1.49中的asio – Jim

回答

0

v0.10 cppnetlib不直接支持客戶端認證。由於您使用cppnetleb可以使用升壓ASIO與提升1.49

下面是一個例子代碼,完成大部分ASIO工作 https://github.com/alexandruc/SimpleHttpsClient/blob/master/https_client.cpp

該代碼是非常相似的http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/ssl/client.cpp

我都在放鏈接中斷的情況。處理該https連接到你需要創建客戶端之前添加以下行的主要功能的客戶端認證:在這個例子中

 std::string tempString = "test.pem"; //this is a pem file that contains a private key and a certificate. 

     boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client); 
     ctx.set_options(boost::asio::ssl::context::default_workarounds 
            | boost::asio::ssl::context::no_sslv2 
            | boost::asio::ssl::context::no_sslv3); 
     ctx.set_default_verify_paths(); 

     ctx.use_certificate_file(tempFileStr.c_str(), boost::asio::ssl::context_base::pem); 
     ctx.use_private_key_file(tempFileStr.c_str(), boost::asio::ssl::context_base::pem); 

但是你沒有一個PEM文件,但P12文件,(PKCS12格式)。 openssl可用於解密並創建deisred pem文件。我修改了以下代碼How to load a PKCS#12 file in OpenSSL programmatically?不幸的是,這個版本的boost不支持內存中的證書,所以它必須被寫入,並被加密到一個文件中。我把它放在臨時目錄中,最後它可能會被刪除。

std::string _certFile = "C:\\cert\\mycert.p12"; 
std::string password = "_certPassword"; 
boost::filesystem::path tempFile = boost::filesystem::temp_directory_path()/"temp.pem"; 
std::string tempFileStr = tempFile.generic_string(); 
std::cout<<"Using temp file " << tempFileStr<<std::endl; 
try 
    { 

     //read in the pksc12 file, decode it and write a PEM file 
     FILE *fp; 
     EVP_PKEY *pkey; 
     X509 *cert; 
     STACK_OF(X509) *ca = NULL; 
     PKCS12 *p12; 
     int i; 

     OpenSSL_add_all_algorithms(); 
     ERR_load_crypto_strings(); 
     if (!(fp = fopen(_certFile.c_str(), "rb"))) { 
      fprintf(stderr, "Error opening file %s\n", _certFile); 
      return false;  
     } 
     p12 = d2i_PKCS12_fp(fp, NULL); 
     fclose (fp); 
     if (!p12) { 
      fprintf(stderr, "Error reading PKCS#12 file\n"); 
      ERR_print_errors_fp(stderr); 
      return false; 
     } 
     if (!PKCS12_parse(p12, _certpPassword.c_str(), &pkey, &cert, &ca)) { 
      fprintf(stderr, "Error parsing PKCS#12 file\n"); 
      ERR_print_errors_fp(stderr); 
      return false; 

     } 
     PKCS12_free(p12); 
     if (!(fp = fopen(tempFileStr.c_str(), "w"))) { 
      fprintf(stderr, "Error opening file %s\n", tempFileStr.c_str()); 
      return false; 
     } 

     if (pkey) { 
      fprintf(fp, "***Private Key***\n"); 
      PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL); 
     } 
     if (cert) { 
      fprintf(fp, "***User Certificate***\n"); 
      PEM_write_X509(fp, cert); 
     } 
     if (ca && sk_X509_num(ca)) { 
      fprintf(fp, "***Other Certificates***\n"); 

      for (i = 0; i < sk_X509_num(ca); i++) 
      { 
       PEM_write_X509(fp, sk_X509_value(ca, i)); 
      } 

     } 

     sk_X509_pop_free(ca, X509_free); 
     X509_free(cert); 
     EVP_PKEY_free(pkey);  
     fclose(fp); 

    } 
    catch (std::exception &e) { 
     retVal = false; 
     std::cout <<"Error parsing/decrypting pkcs12 file into PEM or writing temporary pem file" << e.what() << std::endl;   
    } 

下面是我用

//for ssl connection 
#include <boost/asio.hpp> 
#include <boost/asio/ssl.hpp> 
#include <boost/asio/ssl/context_base.hpp> 

//for parsing key file 
#include <openssl/pkcs12.h>