一切為了迎合蘋果
在WWDC 2016開發者大會上,蘋果宣布了一個最后期限:到2017年1月1日 App Store中的所有應用都必須啟用 App Transport Security安全功能。App Transport Security(ATS)是蘋果在iOS 9中引入的一項隱私保護功能,屏蔽明文HTTP資源加載,連接必須經過更安全的HTTPS。蘋果目前允許開發者暫時關閉ATS,可以繼續使用HTTP連接,但到年底所有官方商店的應用都必須強制性使用ATS。但如果2017年1月1日起您仍一意孤行那么在Apple Store中您的App將不能被用戶下載使用。
兼容HTTP
新特性要求App內訪問的網絡必須使用HTTPS
協議。
但是現在公司的項目使用的是HTTP協議,使用私有加密方式保證數據安全。現在也不能馬上改成HTTPS協議傳輸,需要兼容下HTTP。
網絡請求報錯:The resource could not be loaded because the App Transport Security policy require:
所以先兼容下http:
- 在
Info.plist
中添加NSAppTransportSecurity
類型Dictionary
。 - 在
NSAppTransportSecurity
下添加NSAllowsArbitraryLoads
類型Boolean
,值設為YES
; - 為了適配
webView
中的http鏈接:在NSAppTransportSecurity
下添加Allow Arbitrary Loads in Web Content
類型Boolean
,值設為YES
;
適配HTTPS
iOS開發者來說,需要盡早解決HTTPS請求的問題。
發送HTTPS請求信任SSL證書和自簽名證書,分為三種情況:
- (較少的公司)如果你的app服務端安裝的是SLL頒發的CA,可以使用系統方法直接實現信任SSL證書,關于Apple對SSL證書的要求請參考:蘋果官方文檔CertKeyTrustProgGuide
示例代碼:
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];
- (大部分公司)基于AFNetWorking的SSL特定服務器證書信任處理,使用自簽名證書認證,重寫AFNetWorking的customSecurityPolicy方法。
###驗證證書步驟: - 從服務器要來
.crt
格式的證書,然后用Mac鑰匙串打開,然后導出?.cer
格式的證書
- 把
.cer
證書導入程序的 中。 - 驗證證書的代碼:
/**https證書驗證*/
+(AFSecurityPolicy*)customSecurityPolicy
{// /先導入證書NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"cer"];//證書的路徑NSData *certData = [NSData dataWithContentsOfFile:cerPath];// AFSSLPinningModeCertificate 使用證書驗證模式 (AFSSLPinningModeCertificate是證書所有字段都一樣才通過認證,AFSSLPinningModePublicKey只認證公鑰那一段,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 = (NSSet *)@[certData];return securityPolicy;
}
其中的cerPath
就是app bundle
中證書路徑,certificate
為證書名稱的宏,僅支持cer
格式,securityPolicy
的相關配置尤為重要,請仔細閱讀customSecurityPolicy
方法并根據實際情況設置其屬性。
這樣,就能夠在AFNetWorking的基礎上使用HTTPS協議訪問特定服務器,但是不能信任根證書的CA文件,因此這種方式存在風險,讀取pinnedCertificates中的證書數組的時候有可能失敗,如果證書不符合,certData就會為nil。
- 在發送請求時候 加上這行代碼,https ssl 驗證。
// [[AFHTTPSessionManager manager] setSecurityPolicy:[JYAFNetworkingManager customSecurityPolicy]];
- 更改系統方法,發送異步NSURLConnection請求。
這種方式用的很少就不多介紹了有新區可以自行搜索;
大部分可以參考:
http://www.jianshu.com/p/f312a84a944c
http://www.jianshu.com/p/6b9c8bd5005a
http://www.jianshu.com/p/b03ae4a1a2d3