https://www.cnblogs.com/innchina/p/5554949.html
引言
? ? ? App要上蘋果支付渠道懦冰,蘋果支付票據(jù)容易被人篡改、偽造敢课,造成平臺收益與實際交易額對不上;且由于蘋果支付平臺暫時沒有對賬功能,造成很難區(qū)分真?zhèn)握鸬罚恢荒芴岣邞?yīng)用的安全性,防止支付信息泄露或被篡改氮趋,因此打算引入https這種安全傳輸協(xié)議伍派。
什么是Https,與Http有哪兒些異同
? ? ?HTTPS(全稱:Hypertext Transfer Protocol over Secure Socket Layer)剩胁,是以安全為目標(biāo)的HTTP通道诉植,簡單講是HTTP的安全版。即HTTP下加入SSL層昵观,HTTPS的安全基礎(chǔ)是SSL晾腔,因此加密的詳細(xì)內(nèi)容就需要SSL。 它是一個URI scheme(抽象標(biāo)識符體系)啊犬,句法類同http:體系灼擂。用于安全的HTTP數(shù)據(jù)傳輸。https:URL表明它使用了HTTP觉至,但HTTPS存在不同于HTTP的默認(rèn)端口及一個加密/身份驗證層(在HTTP與TCP之間)剔应。這個系統(tǒng)的最初研發(fā)由網(wǎng)景公司進(jìn)行,提供了身份驗證與加密通訊方法,現(xiàn)在它被廣泛用于萬維網(wǎng)上安全敏感的通訊峻贮,例如交易支付方面席怪。
https協(xié)議需要到ca申請證書,一般免費(fèi)證書很少纤控,需要交費(fèi)挂捻。http是超文本傳輸協(xié)議,信息是明文傳輸船万,https 則是具有安全性的ssl加密傳輸協(xié)議;
http和https使用的是完全不同的連接方式用的端口也不一樣,前者是80,后者是443刻撒。
http的連接很簡單,是無狀態(tài)的,HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸耿导、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議声怔,要比http協(xié)議安全。
HTTPS解決的問題:
1 . 信任主機(jī)的問題. 采用https 的server 必須從CA 申請一個用于證明服務(wù)器用途類型的證書. 該證書只有用于對應(yīng)的server 的時候,客戶度才信任次主機(jī). 所以目前所有的銀行系統(tǒng)網(wǎng)站,關(guān)鍵部分應(yīng)用都是https 的. 客戶通過信任該證書,從而信任了該主機(jī). 其實這樣做效率很低,但是銀行更側(cè)重安全.?
2 . 通訊過程中的數(shù)據(jù)的泄密和被竄改碎节。
(摘自百度百科)
? ? ? HTTP超文本傳輸協(xié)議 (HTTP-Hypertext transfer protocol) 是一種詳細(xì)規(guī)定了瀏覽器和萬維網(wǎng)服務(wù)器之間互相通信的規(guī)則捧搞,通過因特網(wǎng)傳送萬維網(wǎng)文檔的數(shù)據(jù)傳送協(xié)議。
Https請求交互過程
? ? ? 1.peer終端發(fā)送一個request狮荔,https服務(wù)端把支持的加密算法等以證書的形式返回一個身份信息(包含ca頒發(fā)機(jī)構(gòu)和加密公鑰等)胎撇。
? ? ? 2.獲取證書之后,驗證證書合法性殖氏。
? ? ? 3.隨機(jī)產(chǎn)生一個密鑰晚树,并以證書當(dāng)中的公鑰加密。
? ? ? 4.request https服務(wù)端雅采,把用公鑰加密過的密鑰傳送給https服務(wù)端爵憎。
? ? ? 5.https服務(wù)端用自己的密鑰解密,獲取隨機(jī)值婚瓜。
? ? ? 6.之后雙方傳送數(shù)據(jù)都用此密鑰加密后通信宝鼓。
時序圖如下:
第一步:服務(wù)器端配置
1、生成密鑰庫和證書:
因使用java環(huán)境,下面使用jdk下面的keytool工具來生成相應(yīng)的密鑰庫和證書巴刻,下面的命令是在windows 7 下面測試通過的,可以直接復(fù)制使用
1)創(chuàng)建目錄,如d:/sslDemo
2)使用資源管理進(jìn)入d:/sslDemo,按住shift+右鍵,彈出菜單愚铡,選擇"在此處打開命令行".
3)生成服務(wù)器證書庫
keytool -validity 36500 -genkey -v -alias server -keyalg RSA -keystore server.keystore -dname "CN=www.itjoyee.com,OU=itjoyee.com,O=itjoyee.com,L=Wuhan,ST=HuBei,c=cn" -storepass?123456?-keypass?123456
注: 服務(wù)器證書庫參數(shù)“CN”必須與服務(wù)端的IP地址相同,否則會報錯胡陪,客戶端的任意沥寥。(有些信息可有可無,例如L柠座,St等)
回車邑雅,會提示你輸入一些個人信息及組織信息如:
What is your first and last name?
What is the name of your organizational unit?
What is the name of your organization?
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit?
Is correct?
這里輸入yes,回車即可。
公共名稱(cn)應(yīng)該是服務(wù)器的域名妈经。?
JDK中keytool常用命令?
-genkey????? 在用戶主目錄中創(chuàng)建一個默認(rèn)文件".keystore",還會產(chǎn)生一個mykey的別名淮野,mykey中包含用戶的公鑰捧书、私鑰和證書
-alias?????? 產(chǎn)生別名
-keystore??? 指定密鑰庫的名稱(產(chǎn)生的各類信息將不在.keystore文件中
-keyalg????? 指定密鑰的算法
-validity??? 指定創(chuàng)建的證書有效期多少天
-keysize???? 指定密鑰長度
-storepass?? 指定密鑰庫的密碼
-keypass???? 指定別名條目的密碼
-dname?????? 指定證書擁有者信息 例如:? "CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"
-list??????? 顯示密鑰庫中的證書信息????? keytool -list -v -keystore sage -storepass ....
-v?????????? 顯示密鑰庫中的證書詳細(xì)信息
-export????? 將別名指定的證書導(dǎo)出到文件? keytool -export -alias caroot -file caroot.crt
-file??????? 參數(shù)指定導(dǎo)出到文件的文件名
-delete????? 刪除密鑰庫中某條目????????? keytool -delete -alias sage -keystore sage
-keypasswd?? 修改密鑰庫中指定條目口令??? keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage
-import????? 將已簽名數(shù)字證書導(dǎo)入密鑰庫? keytool -import -alias sage -keystore sagely -file sagely.crt
導(dǎo)入已簽名數(shù)字證書用keytool -list -v 以后可以明顯發(fā)現(xiàn)多了認(rèn)證鏈長度,并且把整個CA鏈全部打印出來骤星。
4)從服務(wù)器證書庫中導(dǎo)出服務(wù)器證書(如果是web服務(wù)到此可以結(jié)束)
keytool -export -v -alias server -keystore server.keystore -storepass 123456 -rfc -file server.cer
5)生成客戶端信任證書庫(由服務(wù)端證書生成的證書庫,客戶端使用此證書驗證服務(wù)端來源可靠)
keytool -import -v -alias server -file server.cer -keystore client.truststore -storepass 123456 -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
注:-storetype BKS 是生成android上面可以識別的格式,如果不指定jdk默認(rèn)生成的格式是JKS.
-provider org.bouncycastle.jce.provider.BouncyCastleProvider,需要下載jar包bcprov-jdk16-1.46.jar放到j(luò)dk1.7.0_65\jre\lib\ext\目錄下.
注意需要jdk16,其他的版本android下面有版本不匹配的問題.
6)生成客戶端證書庫
keytool -validity 36500 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore client.p12 -dname "CN=clients.itjoyee.com,OU=jiajianfa,O=jiajianfa,L=Wuhan,ST=HuBei,c=cn" -storepass 123456 -keypass 123456
7)從客戶端證書庫中導(dǎo)出客戶端證書
keytool -export -v -alias client -keystore client.p12 -storetype PKCS12 -storepass 123456 -rfc -file client.cer
注:客戶端證書可以產(chǎn)生多個.
8)將客戶端證書導(dǎo)入到服務(wù)器證書庫(使得服務(wù)器信任客戶端證書,服務(wù)器端用此驗證客戶端的合法性)
keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456
9)查看服務(wù)端證書中信任的客戶端證書
keytool -list -keystore server.keystore -storepass 123456
2鳄厌、服務(wù)器端配置
由于使用tomcat,下面使用tomcat做為實例配置.
2.1、在tomcat安裝目錄下新建key目錄,將上面生成的server.keystore復(fù)制過去.
2.2妈踊、編輯tomcat安裝目錄下的conf目錄下的server.xml,如:d:\sslDemo\apache-tomcat-7.0.55\conf\server.xml
找到Connector,修改如下:
<Connector port="8444" protocol="org.apache.coyote.http11.Http11NioProtocol"
? ? ? ? ? maxThreads="150"
? ? ? ? ? SSLEnabled="true" scheme="https" secure="true"
? ? ? ? ? keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456"
? ? ? ? ? clientAuth="true" sslProtocol="TLS"
? ? ? ? ? truststoreFile="${catalina.base}/key/server.keystore" truststorePass="123456"/>
注:?? ??? ?? ?
port配置https訪問的端口
SSLEnabled="true" 開啟https服務(wù)
scheme="https"
secure="true"?? ?開啟服務(wù)端安全通信,客戶端獲取服務(wù)器端證書
keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456" 服務(wù)器證書庫
clientAuth="true" 開啟驗證客戶端
sslProtocol="TLS" 使用的協(xié)議
truststoreFile="${catalina.base}/key/server.keystore" truststorePass="123456" 服務(wù)器證書庫(已導(dǎo)入客戶端證書)
3、測試
由于生成證書CN配置的是www.itjoyee.com,故需要修改C:\Windows\System32\drivers\etc\hosts
添加
192.168.0.50??? www.itjoyee.com
注:
192.168.0.50 為服務(wù)器的ip
啟動tomcat
打開瀏覽器
地址欄輸入 http://www.itjoyee.com:8080/
可以訪問
地址欄輸入https://www.itjoyee.com:8444/
訪問結(jié)果,為無法顯示,因為泪漂,沒有使服務(wù)器端生成的信任的客戶端證書
雙擊client.p12,輸入密碼,在此訪問https://www.itjoyee.com:8444/
此時會有證書相關(guān)的提示,點擊"確認(rèn)",接著會提示網(wǎng)站安全證書有問題,點擊繼續(xù)訪問,即可進(jìn)入正常訪問頁面
4廊营、tomcat下的服務(wù)強(qiáng)制使用ssl配置
已ROOT服務(wù)為例,修改D:\sslDemo\apache-tomcat-7.0.55\webapps\ROOT\WEB-INF\web.xml
添加
打開瀏覽器
地址欄輸入 http://www.itjoyee.com:8080/會有證書相關(guān)提示
第二步:Android工具類
為了方便測試android下雙向認(rèn)證可以用,生成證書的時候把域名換成服務(wù)器的ip地址,驗證才可以通過。
public class HttpClientSslHelper {
? ? private static final String KEY_STORE_TYPE_BKS = "bks";
? ? private static final String KEY_STORE_TYPE_P12 = "PKCS12";
? ? private static final String SCHEME_HTTPS = "https";
? ? private static final int HTTPS_PORT = 8444;
? ? private static final String KEY_STORE_CLIENT_PATH = "client.p12";
? ? private static final String KEY_STORE_TRUST_PATH = "client.truststore";
? ? private static final String KEY_STORE_PASSWORD = "123456";
? ? private static final String KEY_STORE_TRUST_PASSWORD = "123456";
? ? private static KeyStore keyStore;
? ? private static KeyStore trustStore;
? ? public static HttpClient getSslHttpClient(Context pContext) {
? ? ? ? HttpClient httpsClient = new DefaultHttpClient();
? ? ? ? try {
? ? ? ? ? ? // 服務(wù)器端需要驗證的客戶端證書
? ? ? ? ? ? keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
? ? ? ? ? ? // 客戶端信任的服務(wù)器端證書
? ? ? ? ? ? trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
? ? ? ? ? ? InputStream ksIn = pContext.getResources().getAssets().open(KEY_STORE_CLIENT_PATH);
? ? ? ? ? ? InputStream tsIn = pContext.getResources().getAssets().open(KEY_STORE_TRUST_PATH);
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
? ? ? ? ? ? ? ? trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ksIn.close();
? ? ? ? ? ? ? ? } catch (Exception ignore) {
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? tsIn.close();
? ? ? ? ? ? ? ? } catch (Exception ignore) {
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, KEY_STORE_PASSWORD, trustStore);
? ? ? ? ? ? Scheme sch = new Scheme(SCHEME_HTTPS, socketFactory, HTTPS_PORT);
? ? ? ? ? ? httpsClient.getConnectionManager().getSchemeRegistry().register(sch);
? ? ? ? } catch (KeyManagementException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (UnrecoverableKeyException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (KeyStoreException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (FileNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (NoSuchAlgorithmException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (ClientProtocolException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return httpsClient;
? ? }
}
實例代碼: