本文為投稿文章,原文地址
iOS開發中,AFNetworking以其優雅的結構設計和簡便的調用方式,使其成為了最流行的網絡開源庫之一(另一個應該算是ASI了,但經久失修不維護的原因,已經不是首選)。
我們在大多數情況下,都能夠正確使用AFNetworking的功能,但在網絡安全日趨嚴峻的今天,加入SSL使用HTTPS已經成為了很多大中型網站的首選;這點在國外尤其流行,例如Google已經全站HTTPS。
本文便主要描述了如何正確使用AFNetworking中的SSL功能。詳細步驟如下:
1、獲取到站點的證書:
我們可以使用以下openssl命令來獲取到服務器的公開二進制證書(以google為例):
"openssl s_client -connect www.google.com:443 /dev/null | openssl x509 -outform DER > https.cer"
冒號中的為命令主要部分。該條命令將會在當前路徑下,形成google.com站點的公開二進制證書,命名為https.cer。您可以將www.google.com 替換成您自己的站點以此來獲取您自己站點的https.cer。
2、將證書放進我們的XCode項目工程中:
如上圖所示,將我們的https.cer拖到我們的工程Supporting Files中,把 Copy Items if needed 的勾選上。然後把您的Add to targets 選上,點擊確定。就完成了證書的導入工作。
3、在我們的代碼中使用我們的cer
AFNetworking中的AFSecurityPolicy是主要的類,我們可以這樣來使用它(AFNetworking 2.6.0之前):
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"]; NSData *certData = [NSData dataWithContentsOfFile:cerPath]; AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init]; [securityPolicy setAllowInvalidCertificates:NO]; [securityPolicy setPinnedCertificates:@[certData]]; [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; [securityPolicy setValidatesDomainName:YES]; [securityPolicy setValidatesCertificateChain:NO]; manager.securityPolicy = securityPolicy;
解析:
1)新建一個manager, 地球人都知道
2)在mainBundle中尋找我們剛才拖進項目中的https.cer, 並且將相關的數據讀取出來
3)新建一個AFSecurityPolicy,並進行相應的配置
4)將這個AFSecurityPolicy 實例賦值給manager
也可以這樣來使用:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init]; [securityPolicy setAllowInvalidCertificates:NO]; [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; [securityPolicy setValidatesDomainName:YES]; [securityPolicy setValidatesCertificateChain:NO]; manager.securityPolicy = securityPolicy;
這種方式比前面那種方式要更加簡便一些,主要原因在於AFNetworking會自動去搜索mainBundle下的所有cer結尾的文件並放進內存中;再一一對比。因此在代碼中可以省略不寫。
這樣一個網絡請求的https的安全策略就配置好了,接下來再說明一下幾個AFSecurityPolicy相關的配置
(1)SSLPinningMode
SSLPinningMode 定義了https連接時,如何去校驗服務器端給予的證書。
typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { AFSSLPinningModeNone, AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, };
AFSSLPinningModeNone: 代表客戶端無條件地信任服務器端返回的證書。
AFSSLPinningModePublicKey: 代表客戶端會將服務器端返回的證書與本地保存的證書中,PublicKey的部分進行校驗;如果正確,才繼續進行。
AFSSLPinningModeCertificate: 代表客戶端會將服務器端返回的證書和本地保存的證書中的所有內容,包括PublicKey和證書部分,全部進行校驗;如果正確,才繼續進行。
(2)allowInvalidCertificates
allowInvalidCertificates 定義了客戶端是否信任非法證書。一般來說,每個版本的iOS設備中,都會包含一些既有的CA根證書。如果接收到的證書是iOS信任的CA根證書簽名的,那麼則為合法證書;否則則為“非法”證書。
allowInvalidCertificates 就是用來確認是否信任這樣的證書的。當然,我們也可以給iOS加入新的信任的CA證書。iOS已有的CA根證書,可以在這裡了解到:https://support.apple.com/en-us/HT204132
(3)pinnedCertificates
pinnedCertificates 就是用來校驗服務器返回證書的證書。通常都保存在mainBundle 下。通常默認情況下,AFNetworking會自動尋找在mainBundle的根目錄下所有的.cer文件並保存在pinnedCertificates數組裡,以校驗服務器返回的證書。
(4)validatesDomainName
validatesDomainName 是指是否校驗在證書中的domain這一個字段。每個證書都會包含一個DomainName, 它可以是一個IP地址,一個域名或者一端帶有通配符的域名。如*.google.com, www.google.com 都可以成為這個證書的DomainName。設置validatesDomainName=YES將嚴格地保證其安全性。
(5) validatesCertificateChain
validatesCertificateChain 指的是是否校驗其證書鏈。
通常來講,一個CA證書頒發機構有很多個子機構,用來簽發不同用途的子證書,然後這些子證書又再用來簽發相應的證書。只有證書鏈上的證書都正確,CertificateChain才算驗證完成。以Google為例:
從上圖可以看到,Google.com的證書的根CA證書是GeoTrust Global CA; 而CA並沒有直接給google.com簽證書,而是先簽名了Google Internet Authority G2, 然後G2再簽名了google.com。這時候就需要設備中保存有Google Internet Authority G2證書才能通過校驗。
一般來講,我推薦將validatesCertificateChain設置為NO,因為並不是太有必要做CertificateChain的校驗。並且,在AFNetworking 2.6.0中,也正式將validatesCertificateChain拿掉了(https://github.com/AFNetworking/AFNetworking/blob/master/CHANGELOG.md), 其原因也同樣為:There was no documented security advantage to pinning against an entire certificate chain。
因此,在2.6.0之後,可以不管這個字段。而在此之前,從效率上來說,設定為NO會是個比較明智的選擇。
做好以上工作後,您應該就可以正常訪問您自己的https服務器了。如果還是有問題請檢查:
HTTPS服務器的正確配置。一般來說,可以使用浏覽器打開相同頁面來查看浏覽器上的小鎖是否正常。
是否https.cer正確打包進了項目中。查看第2步中的內容。
其他。跟帖呗。有問題大家一起交流,共同進步:)
這幾個東西別看就這麼一點,理解了好久才理清楚其中代表的含義。接下來打算再寫幾篇關於SSL的詳細博文以紀念這些深度研究的時間。
參考文檔:
https://github.com/AFNetworking/AFNetworking/blob/master/CHANGELOG.md
http://nelson.logdown.com/posts/2015/04/29/how-to-properly-setup-afnetworking-security-connection/