1. 程式人生 > >正確使用AFNetworking的SSL保證網路安全

正確使用AFNetworking的SSL保證網路安全

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專案工程中:

296122-ae2dd8130f0ebbca.png

如上圖所示,將我們的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 set
AllowInvalidCertificates: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為例:

296122-6f830e762e6569e0.png

從上圖可以看到,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/