使用poco 的NetSSL_OpenSSL 搭建https 服務端,使用C++客戶端,java 客戶端訪問,python訪問(python還沒找到帶證書訪問的代碼.)


 

V20161028

由於項目原因,需要用到https去做一些事情.

這兒做了一些相應的研究.

這個https 用起來也是折騰人,還是研究了一周多+之前的一些積累.

 

目錄

1,java client 通過https訪問 C++ 的https server

2,python client 通過https訪問 C++ 的https server

3,C++ 的https server 搭建.

 

1,java client 通過https訪問 C++ 的https server

 

///
//參考代碼:
//http://blog.csdn.net/sunny243788557/article/details/38874153
//http://ln-ydc.iteye.com/blog/1335213
//http://blog.csdn.net/a351945755/article/details/23195713
//http://blog.csdn.net/zhangzuomian/article/details/50324395
//http://blog.csdn.net/henryzhang2009/article/details/38691415

//
//1,先打開網頁,打開證書->詳細信息->復制到文件->第2個選項 base64編碼x.509(.cer) 導出為111.cer

 


//2,使用java/bin 里面的工具

參見:

http://blog.csdn.net/a351945755/article/details/23195713

里面的文章 .

 

 C:\Users\linew>keytool -import -file E:\111.cer -keystore e:\mykeystore.jks

 這個證書是有密碼的,一般都有密碼.

 

 把 e:\mykeystore.jks 改名成 mykeystore.keystore 

這樣java程序,就能識別這個文件流了,

否則會報


java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at SocketClient.Test1.getKeyStore(Test1.java:79)
at SocketClient.Test1.getSSLContext(Test1.java:102)
at SocketClient.Test1.initHttpsURLConnection(Test1.java:139)
at SocketClient.Test1.main(Test1.java:231)
2016-10-28 15:52:22 [MessageReceiver]-[ERROR] java.io.IOException: Invalid keystore format

 

 

java寫的client是用的

http://blog.csdn.net/sunny243788557/article/details/38874153

的.

不過需要注意 . 

MyHostnameVerifier.java里面的內容.
不然 本地不安全的https程序,會報錯.

 

Test1.java的內容

 

package SocketClient;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.dom4j.Document;  
import org.dom4j.DocumentException;  
import org.dom4j.Element;  
import org.dom4j.io.SAXReader;  

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import java.io.BufferedReader;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.security.GeneralSecurityException;  
import java.security.KeyStore;  
  
import javax.net.ssl.HostnameVerifier;  
import javax.net.ssl.HttpsURLConnection;  
import javax.net.ssl.KeyManagerFactory;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.TrustManagerFactory;  


import javax.net.ssl.HostnameVerifier;  
import javax.net.ssl.SSLSession;  

//import MyHostnameVerifier;





public class Test1 {

    static Logger logger = null;
    
    

        /** 
         * 獲得KeyStore. 
         * @param keyStorePath 
         *            密鑰庫路徑 
         * @param password 
         *            密碼 
         * @return 密鑰庫 
         * @throws Exception 
         */  
        public static KeyStore getKeyStore(String password, String keyStorePath)  
                throws Exception {  
            // 實例化密鑰庫  
            KeyStore ks = KeyStore.getInstance("JKS");  
            // 獲得密鑰庫文件流  
            FileInputStream is = new FileInputStream(keyStorePath);  
            // 加載密鑰庫  
            ks.load(is, password.toCharArray());  
            // 關閉密鑰庫文件流  
            is.close();  
            return ks;  
        }  
      
        /** 
         * 獲得SSLSocketFactory. 
         * @param password 
         *            密碼 
         * @param keyStorePath 
         *            密鑰庫路徑 
         * @param trustStorePath 
         *            信任庫路徑 
         * @return SSLSocketFactory 
         * @throws Exception 
         */  
        public static SSLContext getSSLContext(String password,  
                String keyStorePath, String trustStorePath) throws Exception {  
            // 實例化密鑰庫  
            KeyManagerFactory keyManagerFactory = KeyManagerFactory  
                    .getInstance(KeyManagerFactory.getDefaultAlgorithm());  
            // 獲得密鑰庫  
            KeyStore keyStore = getKeyStore(password, keyStorePath);  
            // 初始化密鑰工廠  
            keyManagerFactory.init(keyStore, password.toCharArray());  
      
            // 實例化信任庫  
            TrustManagerFactory trustManagerFactory = TrustManagerFactory  
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());  
            // 獲得信任庫  
            KeyStore trustStore = getKeyStore(password, trustStorePath);  
            // 初始化信任庫  
            trustManagerFactory.init(trustStore);  
            // 實例化SSL上下文  
            SSLContext ctx = SSLContext.getInstance("TLS");  
            // 初始化SSL上下文  
            ctx.init(keyManagerFactory.getKeyManagers(),  
                    trustManagerFactory.getTrustManagers(), null);  
            // 獲得SSLSocketFactory  
            return ctx;  
        }  
      
        /** 
         * 初始化HttpsURLConnection. 
         * @param password 
         *            密碼 
         * @param keyStorePath 
         *            密鑰庫路徑 
         * @param trustStorePath 
         *            信任庫路徑 
         * @throws Exception 
         */  
        public static void initHttpsURLConnection(String password,  
                String keyStorePath, String trustStorePath) throws Exception {  
            // 聲明SSL上下文  
            SSLContext sslContext = null;  
            // 實例化主機名驗證接口  
            HostnameVerifier hnv = new MyHostnameVerifier();  
            try {  
                sslContext = getSSLContext(password, keyStorePath, trustStorePath);  
            } catch (GeneralSecurityException e) {  
                e.printStackTrace();  
            }  
            if (sslContext != null) {  
                HttpsURLConnection.setDefaultSSLSocketFactory(sslContext  
                        .getSocketFactory());  
            }  
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);  
        }  
      
        /** 
         * 發送請求. 
         * @param httpsUrl 
         *            請求的地址 
         * @param xmlStr 
         *            請求的數據 
         */  
        public static void post(String httpsUrl, String xmlStr) {  
            HttpsURLConnection urlCon = null;  
            try {  
                urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();  
                urlCon.setDoInput(true);  
                urlCon.setDoOutput(true);  
                urlCon.setRequestMethod("POST");  
                
                
                urlCon.setRequestProperty("Content-Length",  
                        String.valueOf(xmlStr.getBytes().length));  
                urlCon.setUseCaches(false);  
                //設置為gbk可以解決服務器接收時讀取的數據中文亂碼問題  
                urlCon.getOutputStream().write(xmlStr.getBytes("gbk"));  
                urlCon.getOutputStream().flush();  
                urlCon.getOutputStream().close();  
                
                BufferedReader in = new BufferedReader(new InputStreamReader(  
                        urlCon.getInputStream()));  
                String line;  
                
                System.out.println("收到信息:\r\n");  
                while ((line = in.readLine()) != null) {  
                    System.out.println(line);  
                }  
                


               // urlCon.disconnect();
                
                
//                urlCon.connect();
//                DataOutputStream out = new DataOutputStream(urlCon.getOutputStream());
//                out.write(xmlStr.getBytes("utf-8"));
//                // 刷新、關閉
//                out.flush();
//                out.close();
//                InputStream is = urlCon.getInputStream();
//                if (is != null) {
//                 ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//                 byte[] buffer = new byte[1024];
//                 int len = 0;
//                 while ((len = is.read(buffer)) != -1) {
//                  outStream.write(buffer, 0, len);
//                  //String sxxx(buffer,len);
//                  System.out.println(outStream.toByteArray());  
//                 }
//                 is.close();
//                 //return outStream.toByteArray();
//                }
                
            } catch (MalformedURLException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  

      

        if(urlCon!=null)
        {  
          urlCon.disconnect();
        }


        }  
    
    
    public static void main(String[] args) throws Exception
    {
        
        try 
        {
            
            logger=Logger.getLogger("MessageReceiver"); 
            
            PropertyConfigurator.configure(".\\log4j.properties");
            
            
            int cccd=1;
            

            
            logger.error("信息:");
            
            ///
            //參考代碼:
            //http://blog.csdn.net/sunny243788557/article/details/38874153
            //http://ln-ydc.iteye.com/blog/1335213
            //http://blog.csdn.net/a351945755/article/details/23195713
            //http://blog.csdn.net/zhangzuomian/article/details/50324395
            //http://blog.csdn.net/henryzhang2009/article/details/38691415
            
            //
            //1,先打開網頁,打開證書->詳細信息->復制到文件->第2個選項 base64編碼x.509(.cer) 導出為111.cer
            //2,使用java/bin 里面的工具
            
            //
            ///
            
            // 密碼  
            String password = "secret";  
            // 密鑰庫  
            String keyStorePath = "mykeystore.keystore";  
            // 信任庫  
            String trustStorePath =  "mykeystore.keystore"; 
            // 本地起的https服務  
            String httpsUrl = "https://192.168.0.33:9443/index.html";  
            // 傳輸文本  
            String xmlStr = "JSON=true&key1112=這是測試&key=abc";  
            
//            這是表單
//            String xmlStr = "JSON=true&key1112=這是測試&key=abc";  
            
//          這是這是xml
//            String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><fruitShop>sss</fruitShop>"; 
            
            initHttpsURLConnection(password, keyStorePath, trustStorePath);  
            // 發起請求  
            post(httpsUrl, xmlStr);  
            

        } 
        catch (Exception e) {
            e.printStackTrace();
              logger.error(e.toString());
        }
        
        

    }
    
    
    
}

 

 

 

MyHostnameVerifier.java的內容

package SocketClient;


import javax.net.ssl.HostnameVerifier;  
import javax.net.ssl.SSLSession;  
  
/** 
 * 實現用於主機名驗證的基接口。  
 * 在握手期間,如果 URL 的主機名和服務器的標識主機名不匹配,則驗證機制可以回調此接口的實現程序來確定是否應該允許此連接。 
 */  
public class MyHostnameVerifier implements HostnameVerifier {  
    @Override  
    public boolean verify(String hostname, SSLSession session) {  
//        
//         原因:當訪問HTTPS的網址。您可能已經安裝了服務器證書到您的JRE的keystore 。但這個錯誤是指服務器的名稱與證書實際域名不相等。
//         這通常發生在你使用的是非標准網上簽發的證書。 
//
//         解決方法:讓JRE相信所有的證書和對系統的域名和證書域名。以下是一小段代碼,可以用來實現
        
//        這兒不驗證 
        return true;
        
//        if("localhost".equals(hostname)){  
//            return true;  
//        } else {  
//            return false;  
//        }  
    }  
}  

 

 

訪問結果:

 

 

2,python client 通過https訪問 C++ 的https server

 

不過這種方式 是沒有帶證書的方式去訪問https.

服務端是可能會拒絕的.

服務端可以選擇 是否必須要證書.

#!/usr/bin/env python
# coding:gbk #設置編碼

import sys

import urllib2
import urllib
import  httplib
import httplib2
import cookielib
import socks

from HTMLParser import HTMLParser

import win32com.client

import PIL
import Image
import pytesser

import ConfigParser

import os
import time
import traceback
import  shutil
import uuid
import wmi
import zlib
import pyDes
import random
import json
import pypyodbc
import ssl






import urllib2
import urllib
from cookielib import CookieJar



if __name__=="__main__":#入口函數

    import sys
    reload(sys)
    sys.setdefaultencoding('gbk')

    try:

        # opener = urllib2.build_opener(HTTPSClientAuthHandler('E:/any.pem', 'E:/any.pem') )
        # response = opener.open("https://192.168.0.33:9443/index.html")
        #
        # print response.read()


        # #讀取配置文件
        config = ConfigParser.ConfigParser()
        config.read(sys.argv[0]+".ini")

        HttpsUrl=config.get("Set", "HttpsUrl")

        object_type=config.get("Set", "object_type")
        object_id=config.get("Set", "object_id")
        type=config.get("Set", "type")
        url=config.get("Set", "url")
        sys_name=config.get("Set", "sys_name")

        ssl._create_default_https_context = ssl._create_unverified_context
        cj = CookieJar()
        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
        # input-type values from the html form
        strJson=('''
        {
        "object_type": "%s",
        "object_id": "%s",
        "notify": {
            "type": "%s",
            "url": "%s",
            "ext": {
                    "version": "V2C",
                    "user_name": "ocuser",
                    "user_password": "ocadmin1",
                    "auth_protocol": "SHA",
                    "content_encrypt_protocol": "DES",
                    "encrypt_password": "Huawei123",
                    "sys_name": "%s"
                    }
                }
        }
        '''%(object_type,object_id ,type,url,  sys_name   ))

        formdata = { "data" : strJson}
        data_encoded = urllib.urlencode(formdata)#HttpsUrl
        response = opener.open(HttpsUrl, data_encoded)
        print response
        content = response.read()

        print "---------------\r\n"

        print content
        pass

    except Exception as ex:

        import traceback
        strInfo = traceback.format_exc()
        strInfo=("Exception:%s"%(strInfo))
        print strInfo
        CErrorLogOutput.funFormatOutput((strInfo),sys._getframe().f_code.co_filename,
                                            sys._getframe().f_lineno)
    finally:
        pass

 

3,C++ 的https server 搭建.

 

https 的搭建 先從openssl 的編譯開始吧.

openssl   這個之前一直打交道,一直在用,終於把他完整的編譯了.

 

http://www.cnblogs.com/bleachli/p/5775383.html

 

poco-1.7.6-all\NetSSL_OpenSSL\doc\howtobuild.txt 

有說明

"


Windows
=======

The easiest way to install OpenSSL on Windows is to
use a binary (prebuild) release, for example the
one from Shining Light Productions that comes with
a Windows installer.

1. Download OpenSSL (at least v0.98a) from: 
http://www.slproweb.com/products/Win32OpenSSL.html
2. Install OpenSSL (we assume you install to c:\OpenSSL)
3. Start Visual Studio, go to Tools->Options, under Projects->VC++ Directories
add the following directories:
- Include Files: C:\OpenSSL\include
- Library Files: C:\OpenSSL\lib\VC
4. You are now ready to build NetSSL.

"

 

 

 

之前用的 

poco-1.6.0-all 這個版本,但這個版本的 Crypto 庫與  Win32OpenSSL 有沖突.

后面還是用的原生的

openssl 的庫,來解決這個問題.

 

用了openssl  有lib,NetSSL_OpenSSL 才能正常編譯.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM