1. 程式人生 > >ASIHTTPRequest實現https雙向認證請求

ASIHTTPRequest實現https雙向認證請求

 什麼是雙向認證呢?簡而言之,就是伺服器端對請求它的客戶端要進行身份驗證,客戶端對自己所請求的伺服器也會做身份驗證。服務端一旦驗證到請求自己的客戶端為不可信任的,服務端就拒絕繼續通訊。客戶端如果發現服務端為不可信任的,那麼也中止通訊。

        雙向認證的演算法理論是RSA,(點選此處瞭解RSA演算法原理)。 雙向認證具體又是通過安全證書的方式來實現的,安全證書可用openssl或java程式來生成,用於雙向認證的安全證書中儲存了金鑰對,證書頒發機構信 息,簽名信息,簽名演算法,頒發物件,有效期等資訊。雙向認證中安全證書分為伺服器端證書和客戶端證書,用伺服器端證書中的私鑰對客戶端證書進行簽名,並把 簽名信息寫到客戶端證書中,就得到了被服務端信任的證書。當客戶端請求該服務端時,服務端為拿到客戶端證書資訊,然後取出證書中的簽名信息,用伺服器端證 書的公鑰驗證,如果發現這個客戶端證書確實是伺服器端證書籤名頒發的,那麼通訊就可以繼續進行,否則中斷。

        上面簡單介紹了一下雙向認證和安全證書,那麼我們現在開始正題。

        首先,我們用java生成一個伺服器端證書庫myserverdomain和客戶端證書庫wenfeng.xu,取出伺服器端的證書庫中的證書為客戶端證 書庫簽名並生成PKCS12格式的證書檔案wenfeng.xu.pfx。然後我們將伺服器端證書配置在應用伺服器中,並啟用客戶端認證。以jetty為 例,以下為配置方法:

   啟動應用伺服器,並用與生成服務端證書一致的域名訪問應用(注意這點非常重要,ASIHTTPRequest如果不這麼做是會報錯的,這個域名可以隨便 取,只要更改系統的host配置,讓域名指向服務端ip就行了)。如果你用瀏覽器訪問已啟動的應用,如果看到以下資訊,就可以開始oc客戶端的編碼了。

      在引入了ASIHTTPRequest框架的專案中新建測試類Https.m

C程式碼  收藏程式碼
  1. @implementation Https  
  2. + (void)testClientCertificate {  
  3.     NSURL *httpsUrl = [NSURL URLWithString:@"https://www.myserverdomain.com:8443/smvcj"];//訪問路徑  
  4.     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:httpsUrl];  
  5.     SecIdentityRef identity = NULL;  
  6.     SecTrustRef trust = NULL;  
  7.     //繫結證書,證書放在Resources資料夾中  
  8.     NSData *PKCS12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"wenfeng.xu" ofType:@"pfx"]];//證書檔名和檔案型別  
  9.     [Https extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data];  
  10.     request = [ASIHTTPRequest requestWithURL:httpsUrl];  
  11.     [request setClientCertificateIdentity:identity];//設定訪問路徑  
  12.     [request setValidatesSecureCertificate:NO];//是否驗證伺服器端證書,如果此項為yes那麼伺服器端證書必須為合法的證書機構頒發的,而不能是自己用openssl 或java生成的證書  
  13.     [request startSynchronous];  
  14.     NSError *error = [request error];  
  15.     if (!error) {  
  16.         NSString *response = [request responseString];  
  17.         NSLog(@"response is : %@",response);  
  18.     } else {  
  19.         NSLog(@"Failed to save to data store: %@", [error localizedDescription]);  
  20.         NSLog(@"%@",[error userInfo]);  
  21.     }  
  22. }  
  23. + (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {  
  24.     OSStatus securityError = errSecSuccess;  
  25.     CFStringRef password = CFSTR("[email protected]"); //證書密碼  
  26.     const void *keys[] =   { kSecImportExportPassphrase };  
  27.     const void *values[] = { password };  
  28.     CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys,values, 1,NULL, NULL);  
  29.     CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);  
  30.     //securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,(CFDictionaryRef)optionsDictionary,&items);  
  31.     securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,optionsDictionary,&items);  
  32.     if (securityError == 0) {  
  33.         CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);  
  34.         const void *tempIdentity = NULL;  
  35.         tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);  
  36.         *outIdentity = (SecIdentityRef)tempIdentity;  
  37.         const void *tempTrust = NULL;  
  38.         tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);  
  39.         *outTrust = (SecTrustRef)tempTrust;  
  40.     } else {  
  41.         NSLog(@"Failed with error code %d",(int)securityError);  
  42.         return NO;  
  43.     }  
  44.     return YES;  
  45. }  
  46. @end  

    在專案中呼叫  testClientCertificate方法,發現會報以下錯誤

C程式碼  收藏程式碼
  1. 2014-01-04 15:49:51.194 Mac[661:303] CFNetwork SSLHandshake failed (-9807)  
  2. 2014-01-04 15:49:51.203 Mac[661:303] Failed to save to data store: A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)  
  3. 2014-01-04 15:49:51.204 Mac[661:303] {  
  4.     NSLocalizedDescription = "A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)";  
  5.     NSUnderlyingError = "Error Domain=NSOSStatusErrorDomain Code=-9807 \"The operation couldn\U2019t be completed. (OSStatus error -9807.)\" (errSSLXCertChainInvalid: Invalid certificate chain )";  
  6. }  

  怎麼會這樣?分析最後一句“Invalid certificate chain” 意思是無效的證書鏈。因為每一個證書中都有一個證書鏈,來表示這個證書的層次結構。報這個錯是因為這個客戶端證書的最頂層是我們自己建立的證書,而不是合 法的證書機構頒發的。每個作業系統預設會把一些公認的證書機構頒發的公鑰證書存在系統信認的根證書庫中,以便信任由這些公認的證書機構簽名給其它使用者的證 書。那麼如何在測試環境中避免這個錯?我們只要修改ASIHTTPRequest框架中的相關配置就行了,開啟ASIHTTPRequest.m檔案,查 找“https”關健字,找到

Java程式碼  收藏程式碼
  1. NSMutableDictionary *sslProperties = [NSMutableDictionary dictionaryWithCapacity:1];  

 將其注掉,然後換成以下程式碼

Java程式碼  收藏程式碼
  1. NSMutableDictionary *sslProperties =[[NSMutableDictionary alloc] initWithObjectsAndKeys:  
  2.                                               [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,  
  3.                                               [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,  
  4.                                               [NSNumber numberWithBool:NO],  kCFStreamSSLValidatesCertificateChain,  
  5.                                               kCFNull,kCFStreamSSLPeerName,  
  6.                                               nil];  

 解決我們的錯誤的關鍵程式碼是

     [NSNumber numberWithBool:NO],  kCFStreamSSLValidatesCertificateChain  表示不校驗證書鏈。

儲存一下再執行就可以正常訪問應用了。

相關推薦

ASIHTTPRequest實現https雙向認證請求

 什麼是雙向認證呢?簡而言之,就是伺服器端對請求它的客戶端要進行身份驗證,客戶端對自己所請求的伺服器也會做身份驗證。服務端一旦驗證到請求自己的客戶端為不可信任的,服務端就拒絕繼續通訊。客戶端如果發現服務端為不可信任的,那麼也中止通訊。         雙向認證的演算法

C# https雙向認證,"請求被中止: 未能建立 SSL/TLS 安全通道"解決辦法

最近的專案中用到了呼叫https的介面的功能,編寫出程式後在我自己的電腦上執行沒有問題,但是在同事的電腦上和服務上都沒有辦法正常執行,提示“請求被中止: 未能建立 SSL/TLS 安全通道”,最後在專案經理的幫助下和網上查找了大量的資料,以及做了大量的測試下終於解決了問題,所

JAX-RS RESTful webservice 服務端及客戶端實現(基於HTTPS雙向認證)

在ApacheCXF的Sample裡以及網上很多有關RESTful HTTPS雙向認證的文章介紹僅僅是理論,沒有涉及實際環境的實現(客戶端和服務端都是localhost);這幾天使用Apache的CXF以及 Apache portable HttpClient實現跨IP的J

關於Libcurl雙向認證請求Https

之前通過libcurl開發只是做http請求,這次公司專案需要請求https,所以就研究了一下,其實用libcurl做http請求是非常簡單的,所有底層實現都被封裝到了libcurl裡面(預設編譯的libcurl是沒有附加SSL的,也就是說預設的libcurl是不帶https

HTTPS雙向認證

recv failed https雙向認證 如果需要只支持https可參照 版本說明 httpclinet:4.3.1jdk:1.6tomcat:6 https雙向認證 參考文章 https://blog.csdn.net/zhongming_software/article/details/8592

Retrofit繫結證書實現HTTPS單項認證

客戶端內建伺服器的證書,我們在校驗服務端證書的時候只比對和App內建的證書是否完全相同,如果不同則斷開連線。那麼此時再遭遇中間人攻擊劫持我們的請求時由於黑客伺服器沒有相應的證書,此時HTTPS請求校驗不通過,則無法與黑客的伺服器建立起連線。 那麼接下來我們就結合Retrofit以訪問12306

https雙向認證、證書製作過程

1、生成伺服器證書庫 輸入命令: keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore D:\jks\server.keystore -dname "CN=127.0.0.1,OU=icesoft,O=ices

Tomcat在Apr模式下的Https雙向認證

當tomcat使用Apr模式的時候,如果按照老方法配置https: 控制檯會出現如下錯誤 Connector attribute SSLCertificateFile must be defined when using SSL with APR 直接Google,很多

Java 與 Tomcat 搭配的加密連線:HTTPS 雙向認證

今天遇到的任務是要讓Tomcat 7 支援ssl, schema 從 http 改走 https. Step 1: 為伺服器產生簽章庫 keytool -genkey -v -alias tomcat -keyalg RSA -validity 10000 -keystore ./tomcat.keys

Tomcat伺服器配置https雙向認證

一,HTTPS原理 1,HTTP、HTTPS、SSL、TLS介紹與相互關係 (1) HTTP:平時瀏覽網頁時候使用的一種協議。HTTP協議傳輸的資料都是未加密的(明文),因此使用HTTP協議傳輸隱私資訊非常不安全。 (2)

使用Httpclient實現SSL雙向認證

1、生成伺服器端證書 Java程式碼 keytool -genkey -keyalg RSA -dname "cn=localhost,ou=sango,o=none,l=china,st=beijing,c=cn" -alias server -keypass pa

JAVA實現HTTPS協議POST請求JSON報文

package https; import java.io.ByteArrayOutputStream;   import java.io.DataOutputStream;   import java.io.IOException;   import java.io.InputStream;   impo

Android JSSE實現SSL雙向認證(阻塞模式及非阻塞模式)

      File pfxFile = new File(mCertPath, "ca.pfx");                try {            /*Android支援BKS PKCS12的keystore,不支援JKS,預設為BKS*/            //ksKeys = Ke

Https雙向認證Android客戶端配置

Https雙向認證啊  做了兩遍,第一遍懵懂狀態處於 好不容易做好了,換伺服器,一下子懵了,使出渾身解數又找了一遍,這下終於好了  快哭啦,必須滴要記錄一下,以免以後遇到繼續懵,這裡用retrofit2+okhttp3為例子來簡單說明下 先來說說證書: 服務端提供的證書有四

Apache下配置https雙向認證

1.Apache安裝並開啟ssl 略 2.建立證書 建立證書的步驟如下 2.1建立相關目錄 這裡apache目錄位於/data/webapps/apache 在apache目錄下建立ca目錄(方便管理,可自定義) mkdi

Android Https雙向認證 + GRPC

() pla pan sting ase 根證書 認證 hand cli keywords:android https 雙向認證android GRPC https 雙向認證 ManagedChannel channel = OkHttpChannelBuilder.

tomcat8配置https雙向認證

工具準備:keytool(JDK自帶證書生成工具),tomcat8 利用JDK中keyStore生成證書。 前言: 關於HTTPS介紹文章請看此博文,我也是看了他的博文才搞懂的,真心感謝。 博文地址:http://www.cnblogs.com/JeffreySun/ar

SSL--用Tomcat伺服器配置https雙向認證過程實戰

什麼是https? 百度百科足夠解釋它:http://baike.baidu.com/view/14121.htm 概述 A、 什麼是HTTPS在說HTTPS之前先說說什麼是HTTP,HTTP就是我們平時瀏覽網頁時候使用的一種協議。HTTP協議傳輸的資料都是未加密的,

用Tomcat伺服器配置https雙向認證過程實戰

什麼是https? 百度百科足夠解釋它:http://baike.baidu.com/view/14121.htm工具:keytool (Windows下路徑:%JAVA_HOME%/bin/keytool.exe)環境:Windows8.1企業版、Tomcat-7.0.2

HTTPS雙向認證+USB硬體加密鎖(加密狗)配置

環境:  Ubuntu14.04,apache2.4.7, openssl1.0.1f 安裝apache2 apt-get install apache2 -y 一般openssl預設已經安裝 開啟apache的ssl模組和ssl站點 a2enmod ssl a2ensi