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 搭建.服務器
///
//參考代碼:
//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; // } } }
訪問結果:
不過這種方式 是沒有帶證書的方式去訪問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
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 才能正常編譯.