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

 

V20161028html

因爲項目緣由,須要用到https去作一些事情.java

這兒作了一些相應的研究.python

這個https 用起來也是折騰人,仍是研究了一週多+以前的一些積累.web

 

目錄apache

1,java client 經過https訪問 C++ 的https serverjson

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.cercookie

 


//2,使用java/bin 裏面的工具
session

參見:

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 才能正常編譯.

相關文章
相關標籤/搜索