iOS9網絡適配_ATS:改用更安全的HTTPS

 

iOS9AdaptationTips

iOS9適配系列教程【中文在頁面下方html

(截至2015年9月3日共有6篇,後續還將持續更新。更多iOS開發乾貨,歡迎關注 微博@iOS程序犭袁ios

For more infomation ,welcome to follow my twittergit

Englishgithub

1. Demo1_You'd better Convert HTTP to HTTPS

How to deal with the SSL in iOS9,One solution is to do like: enter image description hereweb

As the Apple say :算法

enter image description here

enter image description here

enter image description here

iOS 9 and OSX 10.11 require TLSv1.2 SSL for all hosts you plan to request data from unless you specify exception domains in your app's Info.plist file.api

The syntax for the Info.plist configuration looks like this:xcode

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow insecure HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

If your application (a third-party web browser, for instance) needs to connect to arbitrary hosts, you can configure it like this:瀏覽器

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

If you're having to do this, it's probably best to update your servers to use TLSv1.2 and SSL, if they're not already doing so. This should be considered a temporary workaround.安全

As of today, the prerelease documentation makes no mention of any of these configuration options in any specific way. Once it does, I'll update the answer to link to the relevant documentation.

If your server is support TLSv1.2 ,but you also have to do what I say just now if you want to connect success in iOS9:

After some discussion with Apple Support, the issue is due to the self signed certificate.

ATS trusts only certificate signed by a well known CA, all others are rejected. As a consequence the only solution with a Self signed certificate is to set an exception with NSExceptionDomains.

2.Demo2_iOS9 new feature in CoreLocation : background only when you need

If you're using CoreLocation framework in your app in Xcode7(pre-released),and you may notice that there is a newly added property called allowsBackgroundLocationUpdates in CLLocationManager class.

This new property is explained in the WWDC session "What's New in Core Location".enter image description here

The default value is NO if you link against iOS 9.

If your app uses location in the background (without showing the blue status bar) you have to setallowsBackgroundLocationUpdates to YES in addition to setting the background mode capability in Info.plist. Otherwise location updates are only delivered in foreground. The advantage is that you can now have location managers with background location updates and other location managers with only foreground location updates in the same app. You can also reset the value to NO to change the behavior.

The documentation is pretty clear about it:

By default, this is NO for applications linked against iOS 9.0 or later, regardless of minimum deployment target.

With UIBackgroundModes set to include "location" in Info.plist, you must also set this property to YES at runtime whenever calling -startUpdatingLocation with the intent to continue in the background.

Setting this property to YES when UIBackgroundModes does not include "location" is a fatal error.

Resetting this property to NO is equivalent to omitting "location" from the UIBackgroundModes value. Access to location is still permitted whenever the application is running (ie not suspended), and has sufficient authorization (ie it has WhenInUse authorization and is in use, or it has Always authorization). However, the app will still be subject to the usual task suspension rules.

See -requestWhenInUseAuthorization and -requestAlwaysAuthorization for more details on possible authorization values.

Set Info.plist like: enter image description here

The syntax for the Info.plist configuration looks like this:

<key>NSLocationAlwaysUsageDescription</key>
<string>微博@iOS程序犭袁 請求後臺定位權限</string>

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

Use like:

_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {
    [_locationManager requestAlwaysAuthorization];
}
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
    _locationManager.allowsBackgroundLocationUpdates = YES;
}
[_locationManager startUpdatingLocation];

3.iOS9 Untrusted Enterprise Developer with no option to trust

Since iOS9 there is no option to trust an enterprise build. Before iOS9,it's very easy to use:if you touch the app,it'll apear this :

enter image description here

Now:

enter image description here

You have to let the user do like: Go to Settings - General - Profiles - tap on your Profile - tap on Trust button.

enter image description here

4.bitcode optional

After Xcode 7,bitcode option will be enabled by default,If your library was compiled without bitcode but the bitcode option is enabled in your project settings.You can

  1. Update your library with bit code, or you'll get warnings like:

(null): URGENT: all bitcode will be dropped because '/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)' was built without bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. Note: This will be an error in the future.

  1. Say NO to Enable Bitcode in your target Build Settings

    enter image description here

and the Library Build Settings to remove the warnings

For more information,go to documentation of bitcode in developer library

,and WWDC 2015 Session 102: "Platforms State of the Union"

enter image description here

5.Privacy and Your App【URL scheme changes】

iOS 9 has made a small change to the handling of URL scheme. You must whitelist the url's that your app will call out to using the LSApplicationQueriesSchemes key in your Info.plist.

Please see post here: http://awkwardhare.com/post/121196006730/quick-take-on-ios-9-url-scheme-changes

The main conclusion is that:

If you call the 「canOpenURL」 method on a URL that is not in your whitelist, it will return 「NO」, even if there is an app installed that has registered to handle this scheme. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.

If you call the 「openURL」 method on a URL that is not in your whitelist, it will fail silently. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.

The author also speculates that this is a bug with the OS and Apple will fix this in a subsequent release.

This is a new security feature of iOS 9. Watch WWDC 2015 Session 703 for more information.

enter image description here

Any app built with SDK 9 needs to provide a LSApplicationQueriesSchemes entry in its plist file, declaring which schemes it attempts to query.

<key>LSApplicationQueriesSchemes</key>
<array>
 <string>urlscheme</string>
 <string>urlscheme2</string>
 <string>urlscheme3</string>
 <string>urlscheme4</string>
</array>

Assuming two apps TestA and TestB. TestB wants to query if TestA is installed. "TestA" defines the following URL scheme in its info.plist file:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>testA</string>
        </array>
    </dict>
</array>

The second app "TestB" tries to find out if "TestA" is installed by calling:

[[UIApplication sharedApplication]
                    canOpenURL:[NSURL URLWithString:@"TestA://"]];

But this will normally return NO in iOS9 because "TestA" needs to be added to the LSApplicationQueriesSchemes entry in TestB's info.plist file. This is done by adding the following code to TestB's info.plist file:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>TestA</string>
</array>

A working implementation can be found here:https://github.com/gatzsche/LSApplicationQueriesSchemes-Working-Example

6. Support Slide Over and Split View of iOS 9

enter image description here How to transition an an older project to support Slide Over and Split View of iOS 9? You may find that all the demo projects was written by storyboard or xib, but the older project's UI is written by code!

I would suggest switching to storyboards to make your life easy.

I would highly recommend you watch the following WWDC videos and then think about what exactly you need to do in order to support multi tasking.

  1. Mysteries of Auto Layout, Part 1

  2. What's New in Storyboards

  3. Implementing UI Designs in Interface Builder

  4. Getting Started with Multitasking on iPad in iOS 9

  5. Optimizing Your App for Multitasking on iPad in iOS

License

Posted by 微博@iOS程序犭袁

Creative Commons BY-NC-ND 3.0

中文

1. Demo1_iOS9網絡適配_ATS:改用更安全的HTTPS

[摘要]爲了強制加強數據訪問安全, iOS9 默認會把 全部的http請求 全部從NSURLConnection 、 CFURL、 NSURLSession發出的 HTTP 請求,都改成 HTTPS 請求:iOS9.x-SDK編譯時,默認會讓全部從NSURLConnection 、 CFURL 、 NSURLSession發出的 HTTP 請求統一採用TLS 1.2 協議。由於 AFNetworking 如今的版本底層使用了 NSURLConnection ,衆多App將被影響(基於iOS8.x-SDK的App不受影響)。服務器所以須要更新,以解析相關數據。如不更新,可經過在 Info.plist 中聲明,倒退回不安全的網絡請求。而這一作法,官方文檔稱爲ATS,全稱爲App Transport Security,是iOS9的一個新特性。

一個符合 ATS 要求的 HTTPS,應該知足以下條件:

  1. Transport Layer Security協議版本要求TLS1.2以上
  2. 服務的Ciphers配置要求支持Forward Secrecy等
  3. 證書籤名算法符合ATS要求等

官方文檔 App Transport Security Technote 對ATS 的介紹:

enter image description here

注:有童鞋反映:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。

那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的NSExceptionDomains,並將大家公司的域名掛在下面。下文也會詳細描述該問題。

官方文檔 App Transport Security Technote 對CA頒發的證書要求:

Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection

在討論以前,跟往常同樣,先說下iOS程序猿們最關心的問題:

跟我有毛關係?須要我加班嗎?!

首先我們來看下業內對Apple這一作法的評論:

enter image description here

這是某社交App上討論,看來業內仍是吐槽聲和確定聲同在。

結論是:

跟你頗有關係,加班吧,少年!

書歸正傳【嚴肅臉】,咱們正式討論下 WHAT,WHY,HOW:

  1. WHAT(什麼是SSL/TLS?跟HTTP和HTTPS有什麼關係)
  2. WHY(之前的HTTP不是也能用嗎?爲何要用SSL/TLS?!Apple是否是又在反人類?)
  3. HOW(如何適配?---弱弱地問下:加班要多久?)

WHAT(什麼是SSL/TLS?跟HTTP和HTTPS有什麼關係)

什麼是SSL/TLS? SSL你必定知道,在此不作贅述。主要說下什麼是TLS,還有跟HTTP和HTTPS有什麼關係。

TLS 是 SSL 新的別稱:

「TLS1.0」之於「SSL3.1」,猶「公元2015」之於「民國104」,「一千克」之於「一公斤」:稱呼不一樣,意思相同。

SSL 3.0版本以後的迭代版本被從新命名爲TLS 1.0:TLS 1.0=SSL 3.1。因此咱們日常也常常見到 「SSL/TLS」 這種說法。

目前,應用最普遍的是TLS 1.0,接下來是SSL 3.0。目前主流瀏覽器都已經實現了TLS 1.2的支持。

經常使用的有下面這些:

  • SSL 2.0
  • SSL 3.0
  • TLS 1.0 (SSL 3.1)
  • TLS 1.1 (SSL 3.1)
  • TLS 1.2 (SSL 3.1)

那爲何標題是「使用HTTPS」而沒有說起SSL和TLS什麼事? 「SSL/TLS」跟HTTP和HTTPS有什麼關係?

要理解這個,要看下他們之間的關係:

HTTP+SSL/TLS+TCP = HTTPS

HTTP+SSL/TLS+TCP

或者

HTTPS = 「HTTP over SSL」

也就是說:

Apple讓你的HTTP採用SSL/TLS協議,就是讓你從HTTP轉到HTTPS。而這一作法,官方文檔稱爲ATS,全稱爲App Transport Security。

WHY(之前的HTTP不是也能用嗎?爲何要用SSL/TLS?Apple是否是又在反人類?)

不使用SSL/TLS的HTTP通訊,就是不加密的通訊!

不使用SSL/TLS的HTTP通訊,全部信息明文傳播,帶來了三大風險:

  1. 竊聽風險(eavesdropping):第三方能夠獲知通訊內容。
  2. 篡改風險(tampering):第三方能夠修改通訊內容。
  3. 冒充風險(pretending):第三方能夠冒充他人身份參與通訊。

SSL/TLS協議是爲了解決這三大風險而設計的,但願達到:

  1. 全部信息都是加密傳播,第三方沒法竊聽。
  2. 具備校驗機制,一旦被篡改,通訊雙方會馬上發現。
  3. 配備身份證書,防止身份被冒充。

SSL/TLS的做用,打個比方來說:

若是原來的 HTTP 是塑料水管,容易被戳破;那麼現在新設計的 HTTPS 就像是在原有的塑料水管以外,再包一層金屬水管(SSL/TLS協議)。一來,原有的塑料水管照樣運行;二來,用金屬加固了以後,不容易被戳破。

HOW(如何適配?---弱弱地問下:加班要多久?)

正如文章開頭所說:

TLS 1.2 協議 強制加強數據訪問安全 系統 Foundation 框架下的「相關網絡請求」將再也不默認使用 HTTP 等不安全的網絡協議,而默認採用 TLS 1.2。服務器所以須要更新,以解析相關數據。如不更新,可經過在 Info.plist 中聲明,倒退回不安全的網絡請求。

總之:

要麼我們iOS程序猿加班,要麼後臺加班:

方案一:當即讓公司的服務端升級使用TLS 1.2,以解析相關數據。

方案二:雖Apple不建議,但可經過在 Info.plist 中聲明,倒退回不安全的網絡請求依然能讓App訪問指定http,甚至任意的http,具體作法見gif圖,示例Demo見 Demo1

enter image description here

這也是官方文檔和WWDC給出的解決方案:

  1. Apple官方文檔enter image description here

  2. WWDC Session: "Networking with NSURLSession" session( 【WWDC 2015 session 703, 「Privacy and Your App」 O網頁連接 】, 時間在30:18左右)

    enter image description here

    enter image description here

    enter image description here

即便你的應用使用的是:你沒有權限控制的CDN (Content Delivery Network),並且它不支持HTTPS!

也別擔憂,Apple都替你考慮好了:

enter image description here正如你在上圖中看到的:蘋果官方提供了一些可選配置項來決定是否開啓ATS模式,也就是能夠選擇開啓或者不開啓。

開發者能夠針對某些肯定的URL不使用ATS,這須要在工程中的info.plist中標記NSExceptionDomains。在NSExceptionDomains字典中,能夠顯式的指定一些不使用ATS的URL。這些你可使用的例子能夠是:

  • NSIncludesSubdomains

  • NSExceptionAllowInsecureHTTPLoads

  • NSExceptionRequiresForwardSecrecy

  • NSExceptionMinimumTLSVersion

  • NSThirdPartyExceptionAllowsInsecureHTTPLoads

  • NSThirdPartyExceptionMinimumTLSVersion

  • NSThirdPartyExceptionRequiresForwardSecrecy

這些關鍵字使咱們能夠更加細緻的設置針對不使用ATS的域名狀況下禁用ATS或者一些特殊的ATS選項。

你可能注意到一些關鍵字像是使用了一些其餘關鍵字中的詞可是在前面加上了"ThirdParty"字樣,好比列表裏最後三個:

  • NSThirdPartyExceptionAllowsInsecureHTTPLoads

  • NSThirdPartyExceptionMinimumTLSVersion

  • NSThirdPartyExceptionRequiresForwardSecrecy

在功能上,這些關鍵字與不含有"ThirdParty"的關鍵字有一樣的效果。並且實際運行中所調用的代碼將會徹底忽略是否使用"ThirdParty"關鍵字。你應該使用適用於你的場景的關鍵字而沒必要過多考慮這些。

關於App Transport Security,每一個應用都屬於4個大類當中的一類。咱們來看看每個大類都是怎樣影響應用的。

-- 分類名 解釋
1. HTTPS Only (只有HTTPS,全部狀況下都使用ATS) 若是你的應用只基於支持HTTPS的服務器,那麼你太幸運了。你的應用不須要作任何改變。可是,注意App Transport Security要求TLS 1.2並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。
2. Mix & Match(混合) 你的應用與一個不符合ATS要求的服務器工做是頗有可能的。在這種狀況下,你須要告訴操做系統哪些站點是涉及到的而後在你的應用的 Info.plist文件中指明哪些要求沒有達到。
3. Opt Out(禁用ATS) 若是你在建立一個網頁瀏覽器,那麼你有一個更大的麻煩。由於你不可能知道你的用戶將要訪問那個網頁,你不可能指明這些網頁是否支持ATS要求且在HTTPS上傳輸。在這種狀況下,除了所有撤銷 App Transport Security 沒有其它辦法。
4. Opt Out With Exceptions(除特殊狀況外,都不使用ATS) 當你的應用撤消了App Transport Security,,但同時定義了一些例外。這很是有用就是當你的應用從不少的服務器上取數據,可是也要與一個你可控的API交互。在這種狀況下,在應用的Info.plist文件中指定任何加載都是被容許的,可是你也指定了一個或多個例外來代表哪些是必需要求 App Transport Security的。

下面分別作一下介紹:

1.HTTPS Only (只有HTTPS,全部狀況下都使用ATS)

若是你的應用只基於支持HTTPS的服務器,那麼你太幸運了。你的應用不須要作任何改變。

惟一須要作的事情就是使用 NSURLSession 。若是你的開發目標是iOS 9或者 OS X EI Capitan以後,ATS 的最佳實踐將會應用到全部基於 NSURLSession 的網絡。

但也有人遇到過這樣的疑惑:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。

那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的NSExceptionDomains,並將大家公司的域名掛在下面。

官方文檔 App Transport Security Technote 對CA頒發的證書要求:

Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection

2.Mix & Match(混合)

你的應用與一個不符合ATS要求的服務器工做是頗有可能的,

當你遇到如下三個不符合 ATS 要求的服務器的域名時:

  1. api.insecuredomain.com
  2. cdn.domain.com
  3. thatotherdomain.com

你能夠分別設置以下:

  1. api.insecuredomain.com

    Info.plist 配置中的XML源碼以下所示:

          <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>api.insecuredomain.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> </dict> </dict>

    在 plist 文件裏顯示以下:

    enter image description here

    咱們定義的第一個「例外」(Exception)告訴ATS當與這個子域交互的時候撤銷了必須使用HTTPS的要求。注意這個僅僅針對在「例外」(Exception)中聲明瞭的子域。很是重要的一點是要理解NSExceptionAllowsInsecureHTTPLoads關鍵字並不只僅只是與使用HTTPS相關。這個「例外」(Exception)指明瞭對於那個域名,全部的App Transport Security的要求都被撤銷了。

  2. cdn.domain.com Info.plist 配置中的XML源碼以下所示:

      <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>cdn.somedomain.com</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> </dict> </dict>

    在 plist 文件裏顯示以下:

    enter image description here

    極可能你的應用是與一個支持HTTPS傳輸數據的服務器交互,可是並無使用TLS 1.2或更高。在這種狀況下,你定義一個「例外」(Exception),它指明應該使用的最小的TLS的版本。這比徹底撤銷那個域名的App Transport Security要更好更安全。

  3. thatotherdomain.com

    Info.plist 配置中的XML源碼以下所示:

         <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>thatotherdomain.com</key> <dict> <!--適用於這個特定域名下的全部子域--> <key>NSIncludesSubdomains</key> <true/> <!--擴展可接受的密碼列表:這個域名可使用不支持 forward secrecy 協議的密碼--> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <!--容許App進行不安全的HTTP請求--> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <!--在這裏聲明所支持的 TLS 最低版本--> <key>NSExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> </dict> </dict>

    在 plist 文件裏顯示以下:

    enter image description here

    NSIncludesSubdomains 關鍵字告訴 App Transport Security 這個「例外」(Exception)適用於這個特定域名的全部子域。這個「例外」(Exception)還進一步經過擴展可接受的密碼列表來定義這個域名可使用不支持forward secrecy( NSExceptionRequiresForwardSecrecy ) 協議的密碼。想了解更多關於forward secrecy的信息,推薦去看官方文檔 Apple's technote 

若是你的App中同時用到了這三個域名,那麼應該是這樣:

     <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>api.insecuredomain.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> <key>cdn.somedomain.com</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> <key>thatotherdomain.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>

enter image description here

3. Opt Out(禁用ATS)

上面是比較嚴謹的作法,指定了能訪問哪些特定的HTTP。固然也有暴力的作法: 完全倒退回不安全的HTTP網絡請求,能任意進行HTTP請求,好比你在開發一款瀏覽器App,或者你想偷懶,或者後臺想偷懶,或者公司不給你升級服務器。。。

你能夠在Info.plist 配置中改用下面的XML源碼:

    <key>NSAppTransportSecurity</key> <dict> <!--完全倒退回不安全的HTTP網絡請求,能任意進行HTTP請求 (不建議這樣作)--> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

在 plist 文件裏顯示以下:

enter image description here

4. Opt Out With Exceptions(除特殊狀況外,都不使用ATS)

上面已經介紹了三種情景,還有一種可能你也會遇到:

當你的應用撤消了App Transport Security,,但同時定義了一些「例外」(Exception)。當你的應用從不少的服務器上取數據,可是也要與一個你可控的API交互。在這種狀況下,在應用的Info.plist文件中指定任何加載都是被容許的,可是你也指定了一個或多個「例外」(Exception)來代表哪些是必需要求 App Transport Security的。下面是Info.plist文件應該會有的內容:

<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> <key>NSExceptionDomains</key> <dict> <key>api.tutsplus.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> </dict> </dict>

在 plist 文件裏顯示以下:

enter image description here

 

【注:以上在Info.plist配置中的作法已經驗證可行,但目前Apple的prerelease版本的官方文檔並未說起Info.plist中配置的代碼,我將密切關注官方文檔,若有說起,再來更新本文 .你若發現官方文檔有說起了,也可在微博@iOS程序犭袁通知下我。】(官方文檔已經有闡述)

 

Certificate Transparency

雖然ATS大多數安全特性都是默承認用的,Certificate Transparency 是必須設置的。若是你有支持Certificate Transparency的證書,你能夠檢查NSRequiresCertificateTransparency關鍵字來使用Certificate Transparency。再次強調,若是你的證書不支持Certificate Transparency,此項須要設置爲不可用。

若是須要調試一些因爲採用了ATS而產生的問題,須要設置CFNETWORK_DIAGNOSTICS爲1,這樣就會打印出包含被訪問的URL和ATS錯誤在內的NSURLSession錯誤信息。要確保處理了遇到的全部的錯誤消息,這樣才能使ATS易於提升可靠性和擴展性。

Q-A

Q:我用xcode7編譯的app,若是不在plist裏面加關鍵字說明,ios9下不能進行網絡請求,由於咱們服務器並不支持 TLS 1.2 ,我要是直接下載app store上的,什麼也沒有作,也是能正常網絡請求。

A:本文中所羅列的新特性,多數狀況下指的是 iOS9.X-SDK 新特性,AppStore 的版本是基於 iOS8.X-SDK或 iOS7.X-SDK,因此並不受 iOS9新特性約束。也就是說:Xcode7給iOS8打設備包能夠請求到網絡,Xcode7給iOS9設備打的包請求不到網絡,Xcode7和iOS9缺一不可,才須要網絡適配ATS。

那麼,如何確認本身項目所使用的 SDK?在Targets->Build Setting-->Architectures

enter image description here

Q:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。

A:那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的NSExceptionDomains,並將大家公司的域名掛在下面。

官方文檔 App Transport Security Technote 對CA頒發的證書要求:

Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection

Q:我使用的是第三方的網絡框架,好比 AFNetworking 、ASIHTTPRequest、CFSocket 等,這個有影響沒有?

A: AFNetworking 有影響,其它沒影響。

ATS 是隻針對 NSURLConnection 、 CFURL 、 NSURLSession ,若是底層涉及到這三個類就會有影響。

如今的 AFNetworking 的 AFHTTPRequestOperationManager 實現是使用的 NSURLConnection 。

但 AFNetworking 也有更新計劃,移除 NSURLConnection 相關API,遷移到 AFHTTPSessionManager ,但還未執行,詳情見:https://github.com/AFNetworking/AFNetworking/issues/2806

Q:試了一下禁用 ATS 的方法 可是仍是沒法聯網 仍然提示要使用https?

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

 

A:遇到這類問題,90%是出如今「一個 Project 多 Target 」的狀況下,因此 請確保你修改的,確實是你的 Target 所屬的 Info.plist !

如何確認?請前往這裏,確認你 Target 所屬的 Info.plist 到底是哪一個:

Project -> Your Target -> Build Settings -> Info.plist File

enter image description here

或者更直截了當一點,直接修改:

Project -> Your Target —>info-> Custom iOS target properties-> 添加禁用 ATS 的屬性

enter image description here

Q:個人項目是「一個 Project 多 Target 」,按照本文禁用 ATS 的方法,是否是每一個 Info.plist 都要修改?

A:不須要,用到哪一個 Target 修改哪一個的 Info.plist ,Target 是獨立的,不受其餘 Target 的影響,也不會影響其餘 Target。

Q:如何檢測咱們公司 HTTPS 是否符合 ATS 的要求?

A: 若是你的 App 的服務也在升級以適配ATS要求,可使用以下的方式進行校驗:

在OS X EI Capitan系統的終端中經過nscurl命令來診斷檢查你的HTTPS服務配置是否知足Apple的ATS要求:

 $ nscurl --verbose --ats-diagnostics https://<your_server_domain>

固然,你也可讓公司服務端的同事參考Apple提供官方指南App Transport Security Technote進行服務的升級配置以知足ATS的要求:

一個符合 ATS 要求的 HTTPS,應該知足以下條件:

  1. Transport Layer Security協議版本要求TLS1.2以上
  2. 服務的Ciphers配置要求支持Forward Secrecy等
  3. 證書籤名算法符合ATS要求等

2.Demo2_iOS9新特性_更靈活的後臺定位

【iOS9在定位的問題上,有一個壞消息一個好消息】壞消息:若是不適配iOS9,就不能偷偷在後臺定位(不帶藍條,見圖)!好消息:將容許出現這種場景:同一App中的多個location manager:一些只能在前臺定位,另外一些可在後臺定位,並可隨時開啓或者關閉特定location manager的後臺定位。

若是沒有請求後臺定位的權限,也是能夠在後臺定位的,不過會帶藍條:enter image description here

如何偷偷在後臺定位:請求後臺定位權限:

// 1. 實例化定位管理器
_locationManager = [[CLLocationManager alloc] init];
// 2. 設置代理
_locationManager.delegate = self;
// 3. 定位精度
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// 4.請求用戶權限:分爲:⓵只在前臺開啓定位⓶在後臺也可定位,
//注意:建議只請求⓵和⓶中的一個,若是兩個權限都須要,只請求⓶便可,
//⓵⓶這樣的順序,將致使bug:第一次啓動程序後,系統將只請求⓵的權限,⓶的權限系統不會請求,只會在下一次啓動應用時請求⓶
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {
    //[_locationManager requestWhenInUseAuthorization];//⓵只在前臺開啓定位
    [_locationManager requestAlwaysAuthorization];//⓶在後臺也可定位
}
// 5.iOS9新特性:將容許出現這種場景:同一app中多個location manager:一些只能在前臺定位,另外一些可在後臺定位(並可隨時禁止其後臺定位)。
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
    _locationManager.allowsBackgroundLocationUpdates = YES;
}
// 6. 更新用戶位置
[_locationManager startUpdatingLocation];

可是若是照着這種方式嘗試,而沒有配置Info.plist,100%你的程序會崩潰掉,並報錯:

*** Assertion failure in -[CLLocationManager setAllowsBackgroundLocationUpdates:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-1808.1.5/Framework/CoreLocation/CLLocationManager.m:593

要將 Info.plist 配置以下:enter image description here

對應的 Info.plist 的XML源碼是:

<key>NSLocationAlwaysUsageDescription</key>
<string>微博@iOS程序犭袁 請求後臺定位權限</string>

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

3.企業級分發

iOS9以前,企業級分發十分方便:點擊App出現「信任按鈕」,

enter image description here

iOS9之後,企業級分發ipa包將遭到與Mac上dmg安裝包同樣的待遇:默認不能安裝,也再也不出現「信任按鈕」

enter image description here

必須讓用戶進行gif圖中的設置(相關Demo:https://github.com/ChenYilong/iOS9AdaptationTips/ )

enter image description here

4.Bitcode

【前言】將來, Watch 應用必須包含 bitcode ,iOS不強制,Mac OS不支持。 但最坑的一點是: Xcode7 及以上版本會默認開啓 bitcode 。

什麼是 bitcode ?

通俗解釋:在線版安卓ART模式。

Apple 官方文檔-- App Distribution Guide – App Thinning (iOS, watchOS) 是這樣定義的:

Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the App Store. Including bitcode will allow Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the store.

翻譯過來就是:

bitcode 是被編譯程序的一種中間形式的代碼。包含 bitcode 配置的程序將會在 App Store 上被編譯和連接。 bitcode 容許蘋果在後期從新優化咱們程序的二進制文件,而不須要咱們從新提交一個新的版本到 App Store 上。

在 Xcode簡介--- What’s New in Xcode-New Features in Xcode 7 中這樣描述:

Bitcode. When you archive for submission to the App Store, Xcode will compile your app into an intermediate representation. The App Store will then compile the bitcode down into the 64 or 32 bit executables as necessary.

也就是

當咱們提交程序到 App Store上時, Xcode 會將程序編譯爲一箇中間表現形式( bitcode )。而後 App store 會再將這個 bitcode 編譯爲可執行的64位或32位程序。

再看看這兩段描述都是放在App Thinning(App瘦身)一節中,能夠看出其與包的優化有關了。

App Thinning 官方文檔解釋以下:

The App Store and operating system optimize the installation of iOS and watchOS apps by tailoring app delivery to the capabilities of the user’s particular device, with minimal footprint. This optimization, called app thinning, lets you create apps that use the most device features, occupy minimum disk space, and accommodate future updates that can be applied by Apple. Faster downloads and more space for other apps and content provides a better user experience.

開發者都知道,當前 iOS App 的編譯打包方式是把適配兼容多個設備的執行文件及資源文件合併一個文件,上傳和下載的文件則包含了全部的這些文件,致使佔用較多的存儲空間。

App Thinning是一個關於節省iOS設備存儲空間的功能,它可讓iOS設備在安裝、更新及運行App等場景中僅下載所需的資源,減小App的佔用空間,從而節省設備的存儲空間。

根據Apple官方文檔的介紹,App Thinning主要有三個機制:

  1. Slicing

    開發者把App安裝包上傳到AppStore後,Apple服務會自動對安裝包切割爲不一樣的應用變體(App variant),當用戶下載安裝包時,系統會根據設備型號下載安裝對應的單個應用變體。

  2. On-Demand Resources

    ORD(隨需資源)是指開發者對資源添加標籤上傳後,系統會根據App運行的狀況,動態下載並加載所需資源,而在存儲空間不足時,自動刪除這類資源。

  3. Bitcode 開啓Bitcode編譯後,可使得開發者上傳App時只需上傳Intermediate Representation(中間件),而非最終的可執行二進制文件。 在用戶下載App以前,AppStore會自動編譯中間件,產生設備所需的執行文件供用戶下載安裝。

(喵大(@onevcat)在其博客 《開發者所須要知道的 iOS 9 SDK 新特性》 中也描述了iOS 9中蘋果在App瘦身中所作的一些改進,你們能夠轉場到那去研讀一下。)

其中,Bitcode的機制能夠支持動態的進行App Slicing,而對於Apple將來進行硬件升級的措施,此機制能夠保證在開發者不從新發布版本的狀況下而兼容新的設備。

Bitcode 是一種中間代碼,那它是什麼格式的呢? LLVM 官方文檔有介紹這種文件的格式: LLVM Bitcode File Format 

若是你的應用也準備啓用 Bitcode 編譯機制,就須要注意如下幾點:

  1. Xcode 7默認開啓 Bitcode ,若是應用開啓 Bitcode,那麼其集成的其餘第三方庫也須要是 Bitcode 編譯的包才能真正進行 Bitcode 編譯
  2. 開啓 Bitcode 編譯後,編譯產生的 .app 體積會變大(中間代碼,不是用戶下載的包),且 .dSYM 文件不能用來崩潰日誌的符號化(用戶下載的包是 Apple 服務從新編譯產生的,有產生新的符號文件)
  3. 經過 Archive 方式上傳 AppStore 的包,能夠在Xcode的Organizer工具中下載對應安裝包的新的符號文件

如何適配?

在上面的錯誤提示中,提到了如何處理咱們遇到的問題:

You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

正如開頭所說的:

將來, Watch 應用必須包含 Bitcode ,iOS不強制,Mac OS不支持。 但最坑的一點是: Xcode7 及以上版本會默認開啓 Bitcode 。

Xcode 7 + 會開啓 Bitcode。

也就是說,也兩種方法適配:

方法一:更新 library 使包含 Bitcode ,不然會出現如下中的警告;

(null): URGENT: all bitcode will be dropped because '/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)' was built without bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. Note: This will be an error in the future.

甚至有的會報錯誤,沒法經過編譯:

ld: ‘/Users//Framework/SDKs/PolymerPay/Library/mobStat/libSDK.a(**ForSDK.o)’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

或:

ld: -undefined and -bitcode_bundle (Xcode setting ENABLE_BITCODE =YES) cannot be used together clang: error: linker command failed with exit code 1 (use -v to see invocation)

enter image description here

不管是警告仍是錯誤,獲得的信息是:咱們引入的一個第三方庫不包含bitcode。

方法二:關閉Bitcode,方法見下圖

enter image description here

咱們能夠在」Build Settings」->」Enable Bitcode」選項中看到:

用 Xcode 7+ 新建一個 iOS 程序時, bitcode 選項默認是設置爲YES的。如今須要改爲NO。

若是咱們開啓了 bitcode ,在提交包時,下面這個界面也會有個 bitcode 選項:

enter image description here

更多信息,請移步

  1. bitcode 蘋果官方文檔

  2. WWDC 2015 Session 102: "Platforms State of the Union"

    enter image description here

5.Demo3---iOS9 URL Scheme 適配_引入白名單概念

WWDC 2015 Session 703: "Privacy and Your App ( 時間在30:18左右)關於 URL scheme 的介紹,指出:

enter image description here

也就是說:在iOS9中,若是使用 canOpenURL: 方法,該方法所涉及到的 URL scheme 必須在"Info.plist"中將它們列爲白名單,不然不能使用。key叫作LSApplicationQueriesSchemes ,鍵值內容是

<key>LSApplicationQueriesSchemes</key>
<array>
 <string>urlscheme</string>
 <string>urlscheme2</string>
 <string>urlscheme3</string>
 <string>urlscheme4</string>
</array>

白名單上限是50個:

WWDC 2015 Session 703: "Privacy and Your App )有說明:

「So for apps that are linked before iOS 9 and are running on iOS 9, they will be given 50 distinct URL schemes.」 -- WWDC 2015 session 703 Privacy and Your App

 

然而,咱們卻發現了一件意外的事: 當咱們在 iOS9-beta(截至本文發佈時,iOS9正式版還未發佈)中,使用 openURL: 方法時,不在白名單中的 URL 會報錯 > 「This app is not allowed to query for scheme xxx」 。 不管是官方文檔仍是 WWDC 的視頻中都沒有說起 openURL: 方法的這一變更,因此猜想這是 beta 版本一個 bug ,截至本文發佈時,iOS9正式版還未發佈,指望在正式版中能得以修復。在此以前,可經過將 openURL: 用到的 URL scheme 列入白名單來解決這個 bug 。(經測試:iOS9 beta5中已經修復)

 

iOS9中 openURL: 方法沒有什麼實質性的變化,僅僅多了一個確認動做:

enter image description here

蘋果爲何要這麼作?

在 iOS9 以前,你可使用 canOpenURL: 監測用戶手機裏到底裝沒裝微信,裝沒裝微博。可是也有一些別有用心的 App ,這些 App 有一張經常使用 App 的 URL scheme,而後他們會屢次調用canOpenURL: 遍歷該表,來監測用戶手機都裝了什麼 App ,好比這個用戶裝了叫「大姨媽」的App,你就能夠知道這個用戶是女性,你就能夠只推給這個用戶女性用品的廣告。這是侵犯用戶隱私的行爲。

這也許就是緣由。

本項目中給出了一個演示用的 Demo ,倉庫的文件夾叫「Demo3_iOS9URLScheme適配_引入白名單概念」,Demo引用自 LSApplicationQueriesSchemes-Working-Example

Demo結構以下:

enter image description here

主要演示的情景是這樣的:

假設有兩個App: weixin(微信) and 個人App. 個人App 想監測 weixin(微信) 是否被安裝了. "weixin(微信)" 在 info.plist 中定義了 URL scheme :

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>weixin</string>
        </array>
    </dict>
</array>

個人App 想監測 weixin(微信) 是否被安裝了 :

[[UIApplication sharedApplication]
                    canOpenURL:[NSURL URLWithString:@"weixin(微信)://"]];

即便你安裝了微信,在iOS9中,這有可能會返回NO:

由於你須要將 "weixin(微信)" 添加到 「個人App」 的 info.plist 文件中:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>weixin</string>
</array>

 

關於 openURL: 這個問題,可在 Demo3 中自行測試,若是該 bug 修復了的話,請私信微博@iOS程序犭袁,我再來更新本文。(經測試:iOS9 beta5中已經修復)

 

另外,推薦一篇博文,其中最關鍵的是如下部分:

If you call the 「canOpenURL」 method on a URL that is not in your whitelist, it will return 「NO」, even if there is an app installed that has registered to handle this scheme. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.

 

> If you call the 「openURL」 method on a URL that is not in your whitelist, it will fail silently. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.

 

Q-A

Q:我用xcode7編譯的app,若是不在plist裏面加scheme,ios9下qq就會不顯示,由於我用了qqsdk裏的判斷是否安裝qq的方法,我要是直接下載app store上的,沒有加scheme,qq也是能顯示。

A:本文中所羅列的新特性,多數狀況下指的是 iOS9.X-SDK 新特性,AppStore 的版本是基於 iOS8.X-SDK或 iOS7.X-SDK,因此並不受 iOS9新特性約束。也就是說:Xcode7給iOS8打設備包不須要白名單也能調用「canOpenURL」 ,Xcode7給iOS9設備打的包則否則,Xcode7和iOS9缺一不可,才須要適配URL Scheme。

那麼,如何確認本身項目所使用的 SDK?在Targets->Build Setting-->Architectures

enter image description here

6. iPad適配Slide Over 和 Split View

enter image description here

【iPad適配Slide Over 和 Split View】 若想適配multi tasking特性,惟一的建議:棄純代碼,改用storyboard、xib,縱觀蘋果WWDC全部Demo均是如此:

  1. Mysteries of Auto Layout, Part 1

  2. What's New in Storyboards

  3. Implementing UI Designs in Interface Builder

  4. Getting Started with Multitasking on iPad in iOS 9

  5. Optimizing Your App for Multitasking on iPad in iOS

結束語

若是你在開發中遇到什麼新的 iOS9 的坑,或者有什麼適配細節本文沒有說起,歡迎給本倉庫提 pull request。也歡迎在微博@iOS程序犭袁 交流。

疏漏之處,可前往閱讀下這個網站,這裏有每一年 WWDC 演講的英文記錄。

相關文章
相關標籤/搜索