你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS10 適配 ATS(app支持https通過App Store審核) 韓俊強的博客

iOS10 適配 ATS(app支持https通過App Store審核) 韓俊強的博客

編輯:IOS開發綜合

一. HTTPS

其實HTTPS從最終的數據解析的角度,與HTTP沒有任何的區別,HTTPS就是將HTTP協議數據包放到SSL/TSL層加密後,在TCP/IP層組成IP數據報去傳輸,以此保證傳輸數據的安全;而對於接收端,在SSL/TSL將接收的數據包解密之後,將數據傳給HTTP協議層,就是普通的HTTP數據。HTTP和SSL/TSL都處於OSI模型的應用層。從HTTP切換到HTTPS是一個非常簡單的過程,在做具體的切換操作之前,我們需要了解幾個概念:

SSL/TLS

為了保證這些隱私數據能加密傳輸,於是網景公司設計了SSL(Secure Sockets Layer)協議用於對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定義在RFC 6101中,之後IETF對SSL 3.0進行了升級,於是出現了TLS(Transport Layer Security) 1.0,定義在RFC 2246。實際上我們現在的HTTPS都是用的TLS協議,但是由於SSL出現的時間比較早,並且依舊被現在浏覽器所支持,因此SSL依然是HTTPS的代名詞,但無論是TLS還是SSL都是上個世紀的事情,SSL最後一個版本是3.0,今後TLS將會繼承SSL優良血統繼續為我們進行加密服務。

SSL/TLS協議運行機制的概述

圖解SSL/TLS協議

簡單的來說,SSL/TSL通過四次握手。SSL協議的工作流程:

服務器認證階段:

客戶端向服務器發送一個開始信息“Hello”以便開始一個新的會話連接;
服務器根據客戶的信息確定是否需要生成新的主密鑰,如需要則服務器在響應客戶的“Hello”信息時將包含生成主密鑰所需的信息;
客戶根據收到的服務器響應信息,產生一個主密鑰,並用服務器的公開密鑰加密後傳給服務器;
服務器恢復該主密鑰,並返回給客戶一個用主密鑰認證的信息,以此讓客戶認證服務器。

用戶認證階段:

在此之前,服務器已經通過了客戶認證,這一階段主要完成對客戶的認證。
經認證的服務器發送一個提問給客戶,客戶則返回(數字)簽名後的提問和其公開密鑰,從而向服務器提供認證。

二. App Transport Security

iOS9中新增App Transport Security(簡稱ATS)特性, 主要使到原來請求的時候用到的HTTP,都轉向TLS1.2協議進行傳輸。這也意味著所有的HTTP協議都強制使用了HTTPS協議進行傳輸。在 iOS 9 和 OS X 10.11 中,默認情況下非 HTTPS 的網絡訪問是被禁止的。當然,因為這樣的推進影響面非常廣,作為緩沖,我們可以在 Info.plist 中添加 NSAppTransportSecurity 字典並且將 NSAllowsArbitraryLoads 設置為 YES 來禁用 ATS。

不過,WWDC 16 中,Apple 表示將繼續在 iOS 10 和 macOS 10.12 裡收緊對普通 HTTP 的訪問限制。從 2017 年 1 月 1 日起,所有的新提交 app 默認是不允許使用 NSAllowsArbitraryLoads 來繞過 ATS 限制的,也就是說,我們最好保證 app 的所有網絡請求都是 HTTPS 加密的,否則可能會在應用審核時遇到麻煩。

三. iOS10 NSAppTransportSecurity

通過在info.plist中配置這個鍵,開發者可以自定義網絡安全策略。例如:

允許針對個別服務器的不安全訪問。
允許不安全的 web 或媒體內容訪問,但不影響整個app的ATS策略。
啟用新的安全特性,例如Certificate Transparency。
對NSAppTransportSecurity的支持自 iOS9.0,OS X v10.11 開始,適用於 app 和 app extension。

自 iOS10.0,macOS 10.12 開始,增加了對下列子鍵的支持:

NSAllowsArbitraryLoadsInMediaNSAllowsArbitraryLoadsInWebContentNSRequiresCertificateTransparencyNSAllowsLocalNetworking

ATS Configuration Basics / ATS 配置基礎知識

對於使用 iOS9.0, OS X v10.11 SDK 及以上的 app 來說,ATS(App Transport Security)默認開啟,NSAllowsArbitraryLoads是字典NSAppTransportSecurity的根鍵,默認值NO。

在啟用 ATS 的情況下,所有的 HTTP 請求必須為 HTTPS(RFC 2818) 連接。任何不安全的 HTTP 請求都將失敗。ATS 使用 TLS(Transport Layer Security)v1.2(RFC 5246)。

下面是字典NSAppTransportSecurity的總體結構,所有鍵都是非必填項:

 

NSAppTransportSecurity : Dictionary {
    NSAllowsArbitraryLoads : Boolean
    NSAllowsArbitraryLoadsInMedia : Boolean
    NSAllowsArbitraryLoadsInWebContent : Boolean
    NSAllowsLocalNetworking : Boolean
    NSExceptionDomains : Dictionary {
         : Dictionary {
            NSIncludesSubdomains : Boolean
            NSExceptionAllowsInsecureHTTPLoads : Boolean
            NSExceptionMinimumTLSVersion : String
            NSExceptionRequiresForwardSecrecy : Boolean   // Default value is YES
            NSRequiresCertificateTransparency : Boolean
        }
    }
}

 

可以看出,所有鍵可以分為兩類:主鍵,這些鍵用來定義 app 的總體 ATS 策略;子鍵,即NSExceptionDomains下面的鍵,使用這些鍵針對某個域名單獨配置。

主鍵包括:

NSAllowsArbitraryLoads

設置為 YES,解除整個 app 的 ATS 限制;但是,通過NSExceptionDomains進 行的配置依然有效。默認值為 NO。
注意:設置為 YES,會引發 App Stroe 的審查,開發者必須說明原因。

NSAllowsArbitraryLoadsInMedia

設置為 YES,解除通過 AV Foundation 框架訪問媒體內容時的 ATS 限制;啟用這個 鍵,務必確保載入的媒體內容已經被加密,例如受FairPlay保護的文件,或者是安全的 HLS流媒,其中不包含敏感的個人信息。默認為 NO。

NSAllowsArbitraryLoadsInWebContent

設置為 YES,解除通過 web view 發出的網絡請求的 ATS 限制。啟用這個鍵,可以使 app 訪問任意網頁內容,但不影響 app 的總體 ATS 策略。此鍵值默認為 NO。

NSAllowsLocalNetworking

設置為 YES,使得 app 可以載入任意本地資源,但不影響 app 的總體 ATS 策略。默 認為 NO。

NSExceptionDomains

為一個或多個域名單獨配置 ATS。
被單獨配置的域名,默認受到完全的 ATS 限制,不管NSAllowsArbitraryLoads的值 如何;需要通過子鍵,進一步配置

所有的子鍵都屬於NSExceptionDomain。向Info.plist中添加這一主鍵:

創建字典,針對一個或多個域名,以便進行 ATS 配置。這意味著之前使用主鍵所做的設置,對於這個域名來說,已經無效。

例如,及時之前設置NSAllowsArbitraryLoadsInMedia為 YES,然而NSExceptionDomain所代表的域名依然不能訪問不安全的媒體內容。

基於這樣的設定,可以針對域名進行 ATS 配置,增加或減少安全措施。例如:

將NSExceptionAllowsInsecureHTTPLoads設置為 YES,就 ;這樣做會引發 App Store 的審查,詳情見App Store Review for ATS。通過配置NSExceptionRequiresForwardSecrecy為 NO,取消正向保密。通過配置NSExceptionMinimumTLSVersion,更改 TLS 最低版本。

NSExceptionDomains字典構成:

<域名字符串>
代表想要配置的特定域名。可以添加多個域名(即添加多個這樣的鍵),為它們統一配置 ATS 策略。這個鍵對應一個字典,包含以下子鍵:

NSIncludesSubdomains
* 設置為 YES,當前域名的 ATS 策略適用於其所有子域名。默認為 NO。
NSExceptionAllowsInsecureHTTPLoads
* 設置為 YES,可以同時通過 HTTP 和 HTTPS 訪問當前域名。默認為 NO。
注意,配置這個鍵值,將引發 App Store 的審查,開發者必須說明原因。
NSExceptionMinimumTLSVersion
* 指定 TLS 的最低版本,因此可以使用版本較低,有安全漏洞的 TLS 協議。
注意,配置這個鍵值,將引發 App Store 的審查,開發者必須說明原因。
NSExceptionRequiresForwardSecrecy
* 設置為 NO,允許針對當前域名使用不支持正向保密的 TLS 加密算法。默認為 YES。
NSRequiresCertificateTransparency
* 設置為 YES,將驗證域名服務器證書的Certificate Transparency時間戳 。默認為 NO。

Requirements for Connecting Using ATS / 使用 ATS 的前提條件

在 ATS 完全開啟的情況下,系統要求 app 的 HTTPS 連接必須滿足以下要求:

X.509 數字證書必須滿足下列標准中的一項:

由操作系統內嵌的根證書頒發機構簽發

由通過操作系統管理員或用戶主動安裝的根證書頒發機構簽發TLS 版本必須為1.2,任何不使用或使用較低版本 TLS / SSL 的連接,都將失敗。

連接必須使用 AES-128 或 AES-256 對稱加密算法。 TLS 算法套裝必須以 ECDSA 密鑰交換的形式支持正向保密,加密算法必須為下面之一:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHATLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHATLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

服務端的葉證書簽名密鑰必須為下面之一:

至少2048位的 RSA 密鑰至少256位的 ECC 密鑰此外,服務器證書的哈希算法必須為 SHA-2,其摘要長度至少位256位(即 SHA-256 及以上)。
上面的標准,未來可能會發生變化。但不會影響到 app 二進制包的兼容性。

\

App Store Review for ATS / App Store 對於 ATS 相關項的審核

某些對 ATS 的配置會引發 App Store 的審核,開發者必須說明原因。這些鍵有:

NSAllowsArbitraryLoadsNSExceptionAllowsInsecureHTTPLoadsNSExceptionMinimumTLSVersion

以下是一些原因說明例子,供參考:

必須連接由其他機構控制的服務器,其還不支持安全連接。必須支持那些還未升級至可使用安全連接,不得不通過公共域名訪問網絡的設備。必須通過 web 展示來源不一的各種網絡內容,但又不能完全使用NSAllowsArbitraryLoadsInWebContent所管理的類。

向 App Store 提交審核時,開發者應主動提供足夠的信息,以便解釋 app 無法使用安全連接的原因。

四. 實現支持安全ATS策略

ATS相關設置對iOS8及以下系統無效

需要解決的問題(iOS 9、iOS10及以上)

1、app內服務器網絡請求訪問支持https(即一般的請求)

2、webview內支持任意http訪問

3、第三方sdk接入與支持http訪問

主要是圍繞info.pilst配置文件作相關的安全ATS策略

Info.plist文件是向操作系統描述應用程序的XML屬性列表,是iPhone應用程序文件夾包含所有重要的Info.plist文件

你可能注意到一些關鍵字像是使用了一些其他關鍵字中的詞但是在前面加上了"ThirdParty"字樣,在功能上,這些關鍵字與不含有"ThirdParty"的關鍵字有同樣的效果。而且實際運行中所調用的代碼將會完全忽略是否使用"ThirdParty"關鍵字。

簡單粗暴的方案:

--------------------------------------------

NSExceptionDomains 的設置方法如下, 比如我們要將 weibo.com 這個域名排除在 ATS 驗證之外,就可以這樣:

 

key>NSAppTransportSecurity

    NSExceptionDomains
    
        weibo.com
        
             NSIncludesSubdomains 
            
             NSExceptionRequiresForwardSecrecy 
            
            NSExceptionAllowsInsecureHTTPLoads
            
        
    
    NSAllowsArbitraryLoads
    


 

注意:每個需添加的域都需要設置此三個屬性。如果請求的網絡圖片是HTTP,也是需要設置的圖片的域。

注意??這個方案風險較大,有可能被拒絕。“需要訪問的域名是第三方服務器,他們沒有進行 HTTPS 對應”會是審核時的一個可選理由,但是這應該只需要針對特定域名,而非全面開放。如果訪問的是自己的服務器的話,可能這個理由會無法通過。

------------------------------------------------

實現方案

1、app內服務器網絡請求訪問支持https

解決方案:

搭建https服務器

搭建https服務器需要ssl證書

ssl自制證書:稱自簽名ssl證書,容易被假冒偽造,浏覽器不信任。(審核不通過)免費CA證書:部分CA機構提供免費的SSL證書,如wosign,starts等(App Store pass掉不通過)付費CA證書:多指企業級及以上的數字證書。

HTTPS服務器滿足ATS默認的條件,而且SSL證書是通過權威的CA機構認證過的,那麼我們在使用Xcode開發的時候,對網絡的適配什麼都不用做,我們也能正常與服務器通信。但是,當我們對安全性有更高的要求時或者我們自建證書時,我們需要本地導入證書來進行驗證。

使用AFNetworking來支持https

AFNetworking是iOS/OSX開發最流行的第三方開源庫之一,現在iOS oc 代碼90%以上都是用這個框架網絡請求。AFNetworking已經將上面的邏輯代碼封裝好,甚至更完善,在AFSecurityPolicy文件中,有興趣可以閱讀這個模塊的代碼;以下就是在AFNetworking 2.6.0以前版本和3.0.0版本基於支持https的驗證方式

步驟:

新建一個manager在mainBundle中尋找我們剛才拖進項目中的https.cer, 並且將相關的數據讀取出來新建一個AFSecurityPolicy,並進行相應的配置將這個AFSecurityPolicy 實例賦值給manager

代碼實現:

 

NSURL * url = [NSURL URLWithString:@"https://www.google.com"];
AFHTTPRequestOperationManager * requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name("kRequestCompletionQueue");
requestOperationManager.completionQueue = requestQueue;

AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認為NO
//如果是需要驗證自建證書,需要設置為YES
securityPolicy.allowInvalidCertificates = YES;

//validatesDomainName 是否需要驗證域名,默認為YES;
//假如證書的域名與你請求的域名不一致,需把該項設置為NO;如設成NO的話,即服務器使用其他可信任機構頒發的證書,也可以建立連接,這個非常危險,建議打開。
//置為NO,主要用於這種情況:客戶端請求的是子域名,而證書上的是另外一個域名。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com,那麼mail.google.com是無法驗證通過的;當然,有錢可以注冊通配符的域名*.google.com,但這個還是比較貴的。
//如置為NO,建議自己添加對應域名的校驗邏輯。
securityPolicy.validatesDomainName = YES;
//validatesCertificateChain 是否驗證整個證書鏈,默認為YES
//設置為YES,會將服務器返回的Trust Object上的證書鏈與本地導入的證書進行對比,這就意味著,假如你的證書鏈是這樣的:
//GeoTrust Global CA 
//    Google Internet Authority G2
//        *.google.com
//那麼,除了導入*.google.com之外,還需要導入證書鏈上所有的CA證書(GeoTrust Global CA, Google Internet Authority G2);
//如是自建證書的時候,可以設置為YES,增強安全性;假如是信任的CA所簽發的證書,則建議關閉該驗證,因為整個證書鏈一一比對是完全沒有必要(請查看源代碼);
securityPolicy.validatesCertificateChain = NO;

requestOperationManager.securityPolicy = securityPolicy;

另afnetworking 3.0.0以上版本用的是AFHTTPSessionManager

 AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
    NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
    NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
    NSLog(@"%@", cerData);
    manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSArray alloc] initWithObjects:cerData, nil]];
    manager.securityPolicy.allowInvalidCertificates = YES;
    [manager.securityPolicy setValidatesDomainName:NO];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    NSDictionary * parameter = @{@"username":self.username, @"password":self.password};
    [manager POST:@"https://192.168.1.4:9777" parameters:parameter success:^(NSURLSessionDataTask * task, id responseObject) {
        NSLog(@"success %@", responseObject);
        }
        failure:^(NSURLSessionDataTask * task, NSError * error) {
            NSLog(@"failure %@", error);
        }]

    NSAppTransportSecurity
    
        NSAllowsArbitraryLoads //設置為 YES,解除整個app的ATS限制;但是通過NSExceptionDomains進行的配置依然有效
        
        NSAllowsArbitraryLoadsInMedia //設置為 YES,解除通過AVFoundation框架訪問媒體內容時的 ATS 限制
        
        NSAllowsArbitraryLoadsInWebContent //設置為 YES,解除通過webview發出的網絡請求的ATS限制
        
        NSAllowsLocalNetworking //設置為 YES,使得app可以載入任意本地資源,但不影響app的總體 ATS 策略
        


 

2、webview內支持任意http訪問

對於網頁浏覽和視頻播放的行為,iOS 10 中新加入了 NSAllowsArbitraryLoadsInWebContent 鍵。通過將它設置為 YES,可以讓 app 中的 WKWebView 和使用 AVFoundation 播放的在線視頻不受 ATS 的限制。這也應該是絕大多數使用了相關特性的 app 的選擇。但是壞消息是這個鍵在 iOS 9 中並不會起作用。

如果app只支持 iOS 10,並且有用戶可以自由輸入網址進行浏覽的功能,或者是在線視頻音頻播放功能的話,簡單地加入 NSAllowsArbitraryLoadsInWebContent,並且將組件換成 WKWebKit 或者 AVFoundation 就可以了。如果你還需要支持 iOS 9,並且需要訪問網頁和視頻的話,可能只能去開啟 NSAllowsArbitraryLoads 然後提交時進行說明,並且看 Apple 審核員決定讓不讓通過了。

另外,當 NSAllowsArbitraryLoads 和 NSAllowsArbitraryLoadsInWebContent 同時存在時,根據系統不同,表現的行為也會不一樣。簡單說,iOS 9 只看 NSAllowsArbitraryLoads,而 iOS 10 會先看 NSAllowsArbitraryLoadsInWebContent。在 iOS 10 中,要是 NSAllowsArbitraryLoadsInWebContent 存在的話,就忽略掉 NSAllowsArbitraryLoads,如果它不存在,則遵循 NSAllowsArbitraryLoads 的設定

UIWebView 在 NSAllowsArbitraryLoadsInWebContent 為 YES 時訪問 HTTP,無效。WKWebView 在 NSAllowsArbitraryLoadsInWebContent 為 YES 時在iOS 10 中訪問 HTTP,有效,iOS 9無效。如果用WkWebView替換UIWebView,iOS 7 將無法使用WkWebView,可做適配加載,沒有特殊的什麼需求的話,盡早將 UIWebView 全部換為 WkWebView 會比較好。所以為了能讓WebView在所有版本都能訪問非https內容,只能把NSAllowsArbitraryLoads設置為YES。

解決方案一:

開啟 NSAllowsArbitraryLoads 為 YES,然後提交時進行說明

解決方案二:

設置 NSExceptionDomains 屬性來訪問指定域名,然後提交時進行說明

3、第三方sdk接入與支持http訪問

但是按照國內的現狀,關閉這個限制也許是更實際的做法。至於原因就太多了,第三方SDK(幾乎都是訪問http),合作伙伴接入(不能要求它們一定要支持https)

第三方sdk,同樣需要遵守ATS規則,即第三方sdk也有被ATS過濾的風險,微信,qq,分享,登陸功能都能正常,微博登陸不能正常通過。另在網上找到了一些可能存在有問題的sdk,目前已知的有:

友盟 (已經有最新的v1.4.0版本sdk,支持https,待驗證)百度地圖

解決方案一:

更新最新sdk,接入並測試

解決方案二:

可以設置 NSExceptionDomains屬性來將需要排除強制驗證的域名寫進來:

五. 總結

開啟 NSAllowsArbitraryLoads 為 YES

對第三方訪問的服務器設置NSExceptionDomains方式添加白名單

提交審核說明:

必須連接由其他機構控制的服務器,其還不支持安全連接。

必須通過 web 展示來源不一的各種網絡內容,但又不能完全使用NSAllowsArbitraryLoadsInWebContent所管理的類。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved