iOS 升級(jí)HTTPS通過ATS你所要知道的

由于蘋果規(guī)定2017年1月1日以后吗讶,所有APP都要使用HTTPS進(jìn)行網(wǎng)絡(luò)請(qǐng)求,否則無法上架仰猖,因此研究了一下在iOS中使用HTTPS請(qǐng)求的實(shí)現(xiàn)明垢。網(wǎng)上搜索了一些比較有用資料,大家可以參考下

蘋果強(qiáng)制升級(jí)的HTTPS不僅僅是在接口HTTP上加個(gè)S那么簡(jiǎn)單:
它所有滿足的是iOS9中新增App Transport Security(簡(jiǎn)稱ATS)特性:
那滿足ATS我們需要做什么呢
1.必須是蘋果信任的CA證書機(jī)構(gòu)頒發(fā)的證書
2.后臺(tái)傳輸協(xié)議必須滿足: TLS1.2 (這很重要, 后面的自制證書滿足這個(gè)條件是前提)
3.簽字算法只能是下面的一種:

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

4.證書必須使用SHA256或者更好的哈希算法進(jìn)行簽名,要么是2048位或者更長(zhǎng)的RSA密鑰频轿,要么就是256位或更長(zhǎng)的ECC密鑰垂涯。

目前有兩種升級(jí)到HTTPS得方法:
1.第三方認(rèn)證的頒發(fā)CA證書(推薦)
2.自己制作證書(這種不知道能不能滿足蘋果的審核)

一: 第三方認(rèn)證的頒發(fā)CA證書

證書到底長(zhǎng)什么樣子呢? 取個(gè)栗子:
大家請(qǐng)打開https://www.baidu.com
然后看到

百度的證書分析
百度的證書分析

那些證書機(jī)構(gòu)頒發(fā)的證書能用:蘋果官方信任證書

收費(fèi)SSL證書: 網(wǎng)上百度一大把, 收費(fèi)還挺貴的,自己可以多找?guī)讉€(gè)對(duì)比一下
免費(fèi)SSL證書: 除了收費(fèi)的CA證書機(jī)構(gòu), 你還可以去騰訊云申請(qǐng)免費(fèi)的SSL證書, 教程免費(fèi)在騰訊云申請(qǐng)SSL證書的方法
沃通(WoSign)免費(fèi)的SSL證書最近被蘋果封殺了, 能不能用大家可以看一下蘋果的公告: 您的蘋果手機(jī)輕點(diǎn)“設(shè)置”>“通用”>“關(guān)于本機(jī)”>"證書信任設(shè)置">"進(jìn)一步了解被信任的證書"去了解

檢測(cè)你的接口是否滿足蘋果的ATS要求, 有以下兩種方法:

1.騰訊云提供的檢測(cè)頁(yè)面檢測(cè)

騰訊云的檢測(cè)頁(yè)面
騰訊云的檢測(cè)頁(yè)面

2 終端輸入 nsurl --ats-diagnostics --verbose 你的接口地址
大家可以參考這篇文章,里面的說的很明白:
關(guān)于iOS9中的App Transport Security相關(guān)說明及適配(更新于2016.7.1)
里面會(huì)詳細(xì)說明你的證書哪點(diǎn)不符合ATS要求
當(dāng)然下面自己制作證書去實(shí)現(xiàn)HTTPS的,檢測(cè)不通過的,所以我覺得審核會(huì)被拒
這種方法配置好了, 在手機(jī)端就什么都不用配置就可以請(qǐng)求了

二: 自己制作證書

蘋果官方信任證書里說到有三種證書:

1 可信的根證書用于建立信任鏈,以驗(yàn)證由可信的根簽署的其他證書航邢,例如耕赘,與 Web 服務(wù)器建立安全連接。當(dāng) IT 管理員創(chuàng)建 iPhone膳殷、iPad 或 iPod touch 的配置描述文件時(shí)操骡,無需提供這些可信的根證書。
2 始終詢問的證書不受信任,但不受阻止册招。使用其中一個(gè)證書時(shí)岔激,系統(tǒng)將提示您選擇是否信任該證書。
3 已阻止的證書視為被盜用是掰,將不再受信任鹦倚。

自制證書我覺得應(yīng)該就是屬于第二種情況, 所以這種方法我也不知道能不能通過蘋果的審核, 只是提供一個(gè)方法給大家參考, 看到網(wǎng)上有人說可以,有人說不可以, 不到1月1號(hào),自己沒試過都不敢說大話
這種方式拿到后臺(tái)的接口用谷歌瀏覽器打開跟百度的證書是有區(qū)別的

自己制作證書
自己制作證書

很明顯沒有綠鎖, 當(dāng)打開的時(shí)候會(huì)詢問是否連接這個(gè)不受信任的連接才會(huì)進(jìn)一步打開, 下面就來一步步的實(shí)現(xiàn)(包括怎么制作證書)
iOS使用自簽名證書實(shí)現(xiàn)HTTPS請(qǐng)求
iOS Https協(xié)議 自簽證書訪問數(shù)據(jù)參考這個(gè)例子的時(shí)候,博主自帶的Demo AFN框架請(qǐng)求不了數(shù)據(jù), 我用了最新AFN版本的成功返回?cái)?shù)據(jù)
還可以參考一下
iOS 10 適配 ATS app支持https通過App Store審核

我在利用原生的代碼測(cè)試時(shí)遇到的問題

@interface ViewController () <NSURLSessionDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
   
   
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
   NSURLSessionDataTask *task =  [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
   [task resume];
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    NSLog(@"接收到服務(wù)器響應(yīng)");
    //注意:這里需要使用completionHandler回調(diào)告訴系統(tǒng)應(yīng)該如何處理服務(wù)器返回的數(shù)據(jù)
    //默認(rèn)是取消
    /**
     NSURLSessionResponseCancel = 0,            默認(rèn)的處理方式,取消
     NSURLSessionResponseAllow = 1,             接收服務(wù)器返回的數(shù)據(jù)
     NSURLSessionResponseBecomeDownload = 2,    變成一個(gè)下載請(qǐng)求
     NSURLSessionResponseBecomeStream           變成一個(gè)流
     */
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data {
    NSLog(@"獲取到服務(wù)段數(shù)據(jù)");
    NSLog(@"%@",[self jsonToDictionary:data]);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error {
    NSLog(@"請(qǐng)求完成%@", error);
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"證書認(rèn)證");
    if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
        do
        {
            SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
            NSCAssert(serverTrust != nil, @"serverTrust is nil");
            if(nil == serverTrust)
                break; /* failed */
            /**
             *  導(dǎo)入多張CA證書(Certification Authority冀惭,支持SSL證書以及自簽名的CA)震叙,請(qǐng)?zhí)鎿Q掉你的證書名稱
             */
            NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"cer"];//自簽名證書
            NSData* caCert = [NSData dataWithContentsOfFile:cerPath];

            NSCAssert(caCert != nil, @"caCert is nil");
            if(nil == caCert)
                break; /* failed */
            
            SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
            NSCAssert(caRef != nil, @"caRef is nil");
            if(nil == caRef)
                break; /* failed */
            
            //可以添加多張證書
            NSArray *caArray = @[(__bridge id)(caRef)];
            
            NSCAssert(caArray != nil, @"caArray is nil");
            if(nil == caArray)
                break; /* failed */
            
            //將讀取的證書設(shè)置為服務(wù)端幀數(shù)的根證書
            OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
            NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
            if(!(errSecSuccess == status))
                break; /* failed */
            
            SecTrustResultType result = -1;
            //通過本地導(dǎo)入的證書來驗(yàn)證服務(wù)器的證書是否可信
            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");
            }

            /* 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 point
            NSLog(@"信任該證書");
            
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
            return [[challenge sender] useCredential: credential
                          forAuthenticationChallenge: challenge];
            
        }
        while(0);
    }
    
    // Bad dog
    NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,credential);
    return [[challenge sender] cancelAuthenticationChallenge: challenge];
}

- (NSDictionary *)jsonToDictionary:(NSData *)jsonData {
    NSError *jsonError;
    NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:&jsonError];
    return resultDic;
}

@end

下面說說我在配置自己制作證書過程中遇到的問題:
1.轉(zhuǎn)換證書: 把后臺(tái)給你的.crt證書轉(zhuǎn)化為.cer后綴
終端命令行openssl x509 -in 你的證書.crt -out 你的證書.cer -outform der

2.利用系統(tǒng)的方法來不到- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler { NSLog(@"證書認(rèn)證"); }這個(gè)方法的時(shí)候, 是因?yàn)楹笈_(tái)的傳輸協(xié)議還沒升級(jí)到TLS1.2, 叫后臺(tái)升級(jí)后就可以來到驗(yàn)證證書的這個(gè)方法了.

3.拖入證書讀取不出證書數(shù)據(jù)
參考: https的證書錯(cuò)誤,錯(cuò)誤碼-1012問題及解決方案

SDWebImage: 項(xiàng)目中大家用到AFN請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù), 升級(jí)驗(yàn)證SSL證書的方案相信你看完上面的參考文章已經(jīng)沒問題了, 我給出的代碼, 自定義網(wǎng)絡(luò)請(qǐng)求也沒問題了, 還有就是SDWebImage框架的請(qǐng)求HTTPS的圖片時(shí),大家可以繞過證書驗(yàn)證去加載圖片[imageView sd_setImageWithURL:[NSURL URLWithString:urlString] placeholderImage:self.placeholder options:SDWebImageAllowInvalidSSLCertificates];

恩, 這就是這幾天升級(jí)HTTPS覺得有幫助的參考和總結(jié).希望幫到你

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末散休,一起剝皮案震驚了整個(gè)濱河市媒楼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戚丸,老刑警劉巖划址,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異限府,居然都是意外死亡夺颤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門胁勺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來世澜,“玉大人,你說我怎么就攤上這事署穗×攘眩” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵案疲,是天一觀的道長(zhǎng)封恰。 經(jīng)常有香客問我,道長(zhǎng)褐啡,這世上最難降的妖魔是什么诺舔? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮备畦,結(jié)果婚禮上低飒,老公的妹妹穿的比我還像新娘。我一直安慰自己萍恕,他們只是感情好逸嘀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著允粤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上类垫,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天司光,我揣著相機(jī)與錄音,去河邊找鬼悉患。 笑死残家,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的售躁。 我是一名探鬼主播坞淮,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼陪捷!你這毒婦竟也來了回窘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤市袖,失蹤者是張志新(化名)和其女友劉穎啡直,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苍碟,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酒觅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了微峰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舷丹。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蜓肆,靈堂內(nèi)的尸體忽然破棺而出掂榔,到底是詐尸還是另有隱情,我是刑警寧澤症杏,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布装获,位于F島的核電站,受9級(jí)特大地震影響厉颤,放射性物質(zhì)發(fā)生泄漏穴豫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一逼友、第九天 我趴在偏房一處隱蔽的房頂上張望精肃。 院中可真熱鬧,春花似錦帜乞、人聲如沸司抱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽习柠。三九已至匀谣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間资溃,已是汗流浹背武翎。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溶锭,地道東北人宝恶。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像趴捅,于是被迫代替她去往敵國(guó)和親垫毙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容