由于我們公司由HTTP轉(zhuǎn)HTTPS,出現(xiàn)了一系列問題特此記錄下。
- 一、HTTPS
- 二、App Transport Security
- 三、iOS 中用HTTPS 注意的問題
- 四、使用 AFNetworking HTTPS 遇到的問題
- 五、問題的解決方法
- 六、注意服務(wù)器端 兩種證書的區(qū)別(以及如何驗證HTTPS服務(wù)器是否符合ATS特性中的要求)
一、HTTPS
HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL層加密后,在TCP/IP層組成IP數(shù)據(jù)報去傳輸,以此保證傳輸數(shù)據(jù)的安全;而對于接收端,在SSL/TSL將接收的數(shù)據(jù)包解密之后,將數(shù)據(jù)傳給HTTP協(xié)議層,就是普通的HTTP數(shù)據(jù)。HTTP和SSL/TSL都處于OSI模型的應(yīng)用層。
二、App Transport Security
iOS9中新增App Transport Security(簡稱ATS)特性, 主要使到原來請求的時候用到的HTTP,都轉(zhuǎn)向TLS1.2協(xié)議進行傳輸。這也意味著所有的HTTP協(xié)議都強制使用了HTTPS協(xié)議進行傳輸。
一般我們?nèi)绻€是使用的http,不更新的話,可通過在 Info.plist 中聲明,倒退回不安全的網(wǎng)絡(luò)請求。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
三、iOS 中用HTTPS 注意的問題
先看文檔中的描述:
These are the App Transport Security requirements:
- The protocol Transport Security Layer (TLS) must be at least version 1.2.
- Connection ciphers are limited to those that provide forward secrecy (see the list of ciphers below.)
- Certificates must use at least an SHA256 fingerprint with either a 2048 bit or greater RSA key, or a 256 bit or greater Elliptic-Curve (ECC) key.
根據(jù)原文描述,首先必須要基于TLS 1.2版本協(xié)議。再來就是連接的加密方式要提供Forward Secrecy,文檔中羅列出支持的加密算法(如下表)。最后就是證書至少要使用一個SHA256的指紋與任一個2048位或者更高位的RSA密鑰,或者是256位或者更高位的ECC密鑰。如果不符合其中一項,請求將被中斷并返回nil。
-
第一條就是TLS版本所需要支持的協(xié)議
第一條滿足 -
第一條就是連接的加密方式需要提供“Foward Secrecy”這個東東,下面是支持Forward Secrecy的加密方式
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256` TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
這是一個滿足條件的證書信息中的情況

但是也要注意證書的合法性,注意是否有效,iOS要求連接的HTTPS站點必須為CA簽名過的合法證書。



注意以上不同的情況決定了AFSecurityPolicy--setAllowInvalidCertificates:是否要驗證證書的有效性。
四、使用AFNetworking HTTPS 遇到的問題(3.0.0之前)
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
//allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認為NO//如果是需要驗證自建證書,需要設(shè)置為YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要驗證域名,默認為YES;
securityPolicy.validatesDomainName = YES;
manager.securityPolicy = securityPolicy;
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:urlString parameters:dic success:finishedBlock failure:failedBlock];
但是剛開始一直不行,不能正常訪問數(shù)據(jù)
- 第一個錯是我打開
Clarles,忘記關(guān)了 - 老出現(xiàn)`Error: Error Domain=NSURLErrorDomain Code=-1012
第二種情況,在google逛了一大圈,試著好幾種方法居然不行,????????,特別是老看到The operation couldn’t be completed. (NSURLErrorDomain error -1012.),頭都大了。。。
五、直到后來找到了一種解決方法...
步驟1:獲取到站點的證書
我們可以使用以下openssl命令來獲取到服務(wù)器的公開二進制證書(以google為例)
openssl s_client -connect www.google.com:443 </dev/null 2>/dev/null | openssl x509 -outform DER > https.cer
冒號中的為命令主要部分。該條命令將會在當前路徑下,形成google.com站點的公開二進制證書,命名為https.cer。您可以將www.google.com 替換成您自己的站點以此來獲取您自己站點的https.cer。
步驟2:導入到Xcode中
直接將https.cer放到資源目錄中就好了,讓我們可以通過pathForResource:獲取到證書,就OK了。

步驟3:代碼導入
NSString *urlString = @"https://www.example.com/app/publicRequest";
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"];
NSData * certData =[NSData dataWithContentsOfFile:cerPath];
NSSet * certSet = [[NSSet alloc] initWithObjects:certData, nil];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// 是否允許,NO-- 不允許無效的證書
[securityPolicy setAllowInvalidCertificates:YES];
// 設(shè)置證書
[securityPolicy setPinnedCertificates:certSet];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// request
[manager GET:urlString parameters:nil progress:^(NSProgress * progress){
} success:^(NSURLSessionDataTask *task, id responseObject) {
NSArray * array = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"OK === %@",array);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"error ==%@",error.description);
}];
然后,就OK了。
六、注意下服務(wù)器端兩種證書的區(qū)別
- 第一種是創(chuàng)建證書請求,然后到權(quán)威機構(gòu)認證,隨之配置到服務(wù)器;
- 第二種是自建證書,需要自己配置給服務(wù)器。
使用第一種還是好一點的,至少在我們 app 端不需要為ATS做過多的適配。但是如何才能知道一個HTTPS服務(wù)器是否符合ATS特性中的要求的呢?使用nscurl命令:
nscurl --ats-diagnostics --verbose https://example.com
下面是測百度時,返回的某一段,結(jié)論是OK的,里面有很多測試的情況,我們可以逐一觀察是否正確。
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"www.baidu.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.0";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
PS:現(xiàn)在我新公司的項目這邊是都不要做之前那種調(diào)整適配的,使用是第一種 權(quán)威 CA 頒發(fā)的那種證書,我們 APP 這端實際上真正的工作量是沒有多少的,所以說關(guān)于HTTPS 適配的這塊:
可以說:在購買到合法的證書時,我們 App 端 基本什么都不用管,改一下URL就好啦。
參考
http://my.oschina.net/vimfung/blog/494687
http://www.itdecent.cn/p/4102b817ff2f
http://oncenote.com/2014/10/21/Security-1-HTTPS/
http://nelson.logdown.com/posts/2015/04/29/how-to-properly-setup-afnetworking-security-connection/
https://zhuanlan.zhihu.com/p/22749689
