日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS开发HTTPS实现之信任SSL证书和自签名证书

發布時間:2024/4/17 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS开发HTTPS实现之信任SSL证书和自签名证书 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先來分析一下什么是HTTPS以及了解HTTPS對于iOS開發者的意義

HTTPS 以及SSL/TSL

  • 什么是SSL?

SSL(Secure Sockets Layer, 安全套接字層),因為原先互聯網上使用的 HTTP 協議是明文的,存在很多缺點,比如傳輸內容會被偷窺(嗅探)和篡改。 SSL 協議的作用就是在傳輸層對網絡連接進行加密。

  • 何為TLS?

到了1999年,SSL 因為應用廣泛,已經成為互聯網上的事實標準。IETF 就在那年把 SSL 標準化。標準化之后的名稱改為 TLS(Transport Layer Security,傳輸層安全協議)。SSL與TLS可以視作同一個東西的不同階段

  • HTTPS

簡單來說,HTTPS = HTTP + SSL/TLS, 也就是 HTTP over SSL 或 HTTP over TLS,這是后面加 S 的由來 。

HTTPS和HTTP異同:HTTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。HTTP的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比HTTP協議安全。

在WWDC 2016開發者大會上,蘋果宣布了一個最后期限:到2017年1月1日 App Store中的所有應用都必須啟用 App Transport Security安全功能。App Transport Security(ATS)是蘋果在iOS 9中引入的一項隱私保護功能,屏蔽明文HTTP資源加載,連接必須經過更安全的HTTPS。蘋果目前允許開發者暫時關閉ATS,可以繼續使用HTTP連接,但到年底所有官方商店的應用都必須強制性使用ATS。

所以對于iOS開發者來說,需要盡早解決HTTPS請求的問題。

發送HTTPS請求信任SSL證書和自簽名證書,分為三種情況

1.如果你的app服務端安裝的是SLL頒發的CA,可以使用系統方法直接實現信任SSL證書,關于Apple對SSL證書的要求請參考:蘋果官方文檔CertKeyTrustProgGuide

這種方式不需要在Bundle中引入CA文件,可以交給系統去判斷服務器端的證書是不是SSL證書,驗證過程也不需要我們去具體實現。

示例代碼:

NSURL?*URL?=?[NSURL?URLWithString:URLString];????NSURLRequest?*request?=?[[NSURLRequest?alloc]?initWithURL:URL?cachePolicy:NSURLRequestReloadIgnoringLocalCacheData?timeoutInterval:10];????//創建同步連接NSError?*error?=?nil;????NSData?*receivedData?=?[NSURLConnection?sendSynchronousRequest:request?returningResponse:nil?error:&error];????NSString?*receivedInfo?=?[[NSString?alloc]?initWithData:receivedData?encoding:NSUTF8StringEncoding];

當然,如果你需要同時信任SSL證書和自簽名證書的話還是需要在代碼中實現CA的驗證,這種情況在后面會提到。

2.基于AFNetWorking的SSL特定服務器證書信任處理,重寫AFNetWorking的customSecurityPolicy方法,這里我創建了一個HttpRequest類,分別對GET和POST方法進行了封裝,以GET方法為例:

+?(void)get:(NSString?*)url?params:(NSDictionary?*)params?success:(void?(^)(id))success?failure:(void?(^)(NSError?*))failure?{????//?1.獲得請求管理者AFHTTPRequestOperationManager?*mgr?=?[AFHTTPRequestOperationManager?manager];????//?2.申明返回的結果是text/html類型mgr.responseSerializer?=?[AFHTTPResponseSerializer?serializer];????//?3.設置超時時間為10smgr.requestSerializer.timeoutInterval?=?10;????//?加上這行代碼,https?ssl?驗證。if(openHttpsSSL)?{[mgr?setSecurityPolicy:[self?customSecurityPolicy]];}????//?4.發送GET請求[mgr?GET:url?parameters:params?success:^(AFHTTPRequestOperation?*operation,?id?responseObj){????????if?(success)?{success(responseObj);}}?failure:^(AFHTTPRequestOperation?*operation,?NSError?*error)?{????????if?(error)?{failure(error);}}]; }+?(AFSecurityPolicy*)customSecurityPolicy?{????//?/先導入證書NSString?*cerPath?=?[[NSBundle?mainBundle]?pathForResource:certificate?ofType:@"cer"];//證書的路徑NSData?*certData?=?[NSData?dataWithContentsOfFile:cerPath];????//?AFSSLPinningModeCertificate?使用證書驗證模式AFSecurityPolicy?*securityPolicy?=?[AFSecurityPolicy?policyWithPinningMode:AFSSLPinningModeCertificate];????//?allowInvalidCertificates?是否允許無效證書(也就是自建的證書),默認為NO//?如果是需要驗證自建證書,需要設置為YESsecurityPolicy.allowInvalidCertificates?=?YES;????//validatesDomainName?是否需要驗證域名,默認為YES;//假如證書的域名與你請求的域名不一致,需把該項設置為NO;如設成NO的話,即服務器使用其他可信任機構頒發的證書,也可以建立連接,這個非常危險,建議打開。//置為NO,主要用于這種情況:客戶端請求的是子域名,而證書上的是另外一個域名。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com,那么mail.google.com是無法驗證通過的;當然,有錢可以注冊通配符的域名*.google.com,但這個還是比較貴的。//如置為NO,建議自己添加對應域名的校驗邏輯。securityPolicy.validatesDomainName?=?NO;securityPolicy.pinnedCertificates?=?@[certData];????return?securityPolicy; }

其中的cerPath就是app bundle中證書路徑,certificate為證書名稱的宏,僅支持cer格式,securityPolicy的相關配置尤為重要,請仔細閱讀customSecurityPolicy方法并根據實際情況設置其屬性。

這樣,就能夠在AFNetWorking的基礎上使用HTTPS協議訪問特定服務器,但是不能信任根證書的CA文件,因此這種方式存在風險,讀取pinnedCertificates中的證書數組的時候有可能失敗,如果證書不符合,certData就會為nil。

3.更改系統方法,發送異步NSURLConnection請求。

-?(void)getDataWithURLRequest?{????//connectionNSString?*urlStr?=?@"https://developer.apple.com/cn/";????NSURL?*url?=?[NSURL?URLWithString:urlStr];????NSMutableURLRequest?*request?=?[NSMutableURLRequest?requestWithURL:url?cachePolicy:NSURLRequestUseProtocolCachePolicy?timeoutInterval:10];????NSURLConnection?*connection?=?[[NSURLConnection?alloc]initWithRequest:request?delegate:self];[connection?start]; }

重點在于處理NSURLConnection的didReceiveAuthenticationChallenge代理方法,對CA文件進行驗證,并建立信任連接。

-?(BOOL)connection:(NSURLConnection?*)connection?canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace?*)protectionSpace?{????return?[protectionSpace.authenticationMethod?isEqualToString:NSURLAuthenticationMethodServerTrust]; }-?(void)connection:(NSURLConnection?*)connection?didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge?*)challenge?{?/*//直接驗證服務器是否被認證(serverTrust),這種方式直接忽略證書驗證,直接建立連接,但不能過濾其它URL連接,可以理解為一種折衷的處理方式,實際上并不安全,因此不推薦。SecTrustRef?serverTrust?=?[[challenge?protectionSpace]?serverTrust];return?[[challenge?sender]?useCredential:?[NSURLCredential?credentialForTrust:?serverTrust]forAuthenticationChallenge:?challenge];*/if?([[[challenge?protectionSpace]?authenticationMethod]?isEqualToString:?NSURLAuthenticationMethodServerTrust])?{????????do{SecTrustRef?serverTrust?=?[[challenge?protectionSpace]?serverTrust];????????????NSCAssert(serverTrust?!=?nil,?@"serverTrust?is?nil");????????????if(nil?==?serverTrust)????????????????break;?/*?failed?*//***??導入多張CA證書(Certification?Authority,支持SSL證書以及自簽名的CA)*/NSString?*cerPath?=?[[NSBundle?mainBundle]?pathForResource:@"cloudwin"?ofType:@"cer"];//自簽名證書NSData*?caCert?=?[NSData?dataWithContentsOfFile:cerPath];????????????NSString?*cerPath2?=?[[NSBundle?mainBundle]?pathForResource:@"apple"?ofType:@"cer"];//SSL證書NSData?*?caCert2?=?[NSData?dataWithContentsOfFile:cerPath2];????????????NSCAssert(caCert?!=?nil,?@"caCert?is?nil");????????????if(nil?==?caCert)????????????????break;?/*?failed?*/NSCAssert(caCert2?!=?nil,?@"caCert2?is?nil");????????????if?(nil?==?caCert2)?{????????????????break;}SecCertificateRef?caRef?=?SecCertificateCreateWithData(NULL,?(__bridge?CFDataRef)caCert);????????????NSCAssert(caRef?!=?nil,?@"caRef?is?nil");????????????if(nil?==?caRef)????????????????break;?/*?failed?*/SecCertificateRef?caRef2?=?SecCertificateCreateWithData(NULL,?(__bridge?CFDataRef)caCert2);????????????NSCAssert(caRef2?!=?nil,?@"caRef2?is?nil");????????????if(nil?==?caRef2)????????????????break;?/*?failed?*/NSArray?*caArray?=?@[(__bridge?id)(caRef),(__bridge?id)(caRef2)];????????????NSCAssert(caArray?!=?nil,?@"caArray?is?nil");????????????if(nil?==?caArray)????????????????break;?/*?failed?*/OSStatus?status?=?SecTrustSetAnchorCertificates(serverTrust,?(__bridge?CFArrayRef)caArray);????????????NSCAssert(errSecSuccess?==?status,?@"SecTrustSetAnchorCertificates?failed");????????????if(!(errSecSuccess?==?status))????????????????break;?/*?failed?*/SecTrustResultType?result?=?-1;status?=?SecTrustEvaluate(serverTrust,?&result);????????????if(!(errSecSuccess?==?status))????????????????break;?/*?failed?*/NSLog(@"stutas:%d",(int)status);????????????NSLog(@"Result:?%d",?result);????????????BOOL?allowConnect?=?(result?==?kSecTrustResultUnspecified)?||?(result?==?kSecTrustResultProceed);????????????if?(allowConnect)?{????????????????NSLog(@"success");}else?{????????????????NSLog(@"error");}????????????/*?https://developer.apple.com/library/ios/technotes/tn2232/_index.html?*//*?https://developer.apple.com/library/mac/qa/qa1360/_index.html?*//*?kSecTrustResultUnspecified?and?kSecTrustResultProceed?are?success?*/if(!?allowConnect){????????????break;?/*?failed?*/}#if?0/*?Treat?kSecTrustResultConfirm?and?kSecTrustResultRecoverableTrustFailure?as?success?*//*???since?the?user?will?likely?tap-through?to?see?the?dancing?bunnies?*/if(result?==?kSecTrustResultDeny?||?result?==?kSecTrustResultFatalTrustFailure?||?result?==?kSecTrustResultOtherError)????????????????break;?/*?failed?to?trust?cert?(good?in?this?case)?*/#endif//?The?only?good?exit?pointreturn?[[challenge?sender]?useCredential:?[NSURLCredential?credentialForTrust:?serverTrust]forAuthenticationChallenge:?challenge];}?while(0);}????//?Bad?dogreturn?[[challenge?sender]?cancelAuthenticationChallenge:?challenge];}

這里的關鍵在于result參數的值,根據官方文檔的說明,判斷(result == kSecTrustResultUnspecified) || (result == kSecTrustResultProceed)的值,若為1,則該網站的CA被app信任成功,可以建立數據連接,這意味著所有由該CA簽發的各個服務器證書都被信任,而訪問其它沒有被信任的任何網站都會連接失敗。該CA文件既可以是SLL也可以是自簽名。

NSURLConnection的其它代理方法實現

#pragma?mark?--?connect的異步代理方法-(void)connection:(NSURLConnection?*)connection?didReceiveResponse:(NSURLResponse?*)response?{????NSLog(@"請求被響應");_mData?=?[[NSMutableData?alloc]init]; }-(void)connection:(NSURLConnection?*)connection?didReceiveData:(nonnull?NSData?*)data?{????NSLog(@"開始返回數據片段");[_mData?appendData:data]; }-(void)connectionDidFinishLoading:(NSURLConnection?*)connection?{????NSLog(@"鏈接完成");????//可以在此解析數據NSString?*receiveInfo?=?[NSJSONSerialization?JSONObjectWithData:self.mData?options:NSJSONReadingAllowFragments?error:nil];????NSLog(@"received?data:\\\\n%@",self.mData);????NSLog(@"received?info:\\\\n%@",receiveInfo); }//鏈接出錯-(void)connection:(NSURLConnection?*)connection?didFailWithError:(NSError?*)error?{????NSLog(@"error?-?%@",error); }

至此,HTTPS信任證書的問題得以解決,這不僅是為了響應Apple強制性使用ATS的要求,也是為了實際生產環境安全性的考慮,HTTPS是未來的趨勢,建議盡早支持。

如需參考Demo請移步本人在Github上的開源項目



文/無忌不悔(簡書作者)
原文鏈接:http://www.jianshu.com/p/6b9c8bd5005a#
著作權歸作者所有,轉載請聯系作者獲得授權,并標注“簡書作者”。


轉載于:https://blog.51cto.com/ljianbing/1874196

總結

以上是生活随笔為你收集整理的iOS开发HTTPS实现之信任SSL证书和自签名证书的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。