1. App Transport Security
-
Protecting Customer Data
- What is App Transport Security (ATS)?
- Disallows cleartext HTTP URL loads
- Encourages best practice secure connections
- Defaults to stronger security
- Allows configuration via app's Info.plist
NSAppTransportSecurity
NSExceptionDomains
"example.com"
NSIncludesSubdomains = YES
NSExceptionRequiresForwardSecrecy = NO
NSExceptionMinimumTLSVersion = "TLSv1.1"
NSAppTransportSecurity
NSExceptionDomains
"media.example.com"
NSExceptionAllowsInsecureHTTPLoads = YES
NSAppTransportSecurity
NSAllowsArbitraryLoads = YES
NSAppTransportSecurity NSAllowsArbitraryLoads
NSExceptionDomains
"secure.example.com"
NSExceptionAllowsInsecureHTTPLoads = NO
-
Configuring ATS
-
Diagnosing issues
- Active when you build your app for iOS 9 and OS X El Capitan
- "http://" to "https://" is automatic
- Use
NSAllowsArbitrary
Loads for quick triage - Log NSURLSession errors
- CFNETWORK_DIAGNOSTICS=1
-
Protecting Customer Data
-
Next steps
- Use HTTPS for new projects
- Transition existing apps from HTTP to HTTPS
- Use exceptions where needed
2. New Protocol Support in NSURLSession
-
HTTP/2
- Adoption on the client
- NSURLSession supports HTTP/2 protocol automatically
- No source code changes needed
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig)
let url = NSURL(string: "https://www.example.com")!
let task = session.dataTaskWithURL(url) {
(data: NSData?, response: NSURLResponse?, error: NSError?) in
...
}task?.resume()
3. API Changes
-
NSURLConnection
-
Deprecated in OS X 10.11 and iOS 9.0
- Not going away, apps using it will still work
- New features will be added to NSURLSession
Not supported on watchOS
Switching to NSURLSession is easy
-
Switching to NSURLSession
let queue: NSOperationQueue = ... let url = NSURL(string: "https://www.example.com")! let request = NSURLRequest(URL: url) NSURLConnection.sendAsynchronousRequest(request, queue: queue) { (response: NSURLResponse?, data: NSData?, error: NSError?) in ... }
let queue: NSOperationQueue = ...
let url = NSURL(string: "https://www.example.com")!
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: queue) {
(response: NSURLResponse?, data: NSData?, error: NSError?) in
...
}
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data: NSData?, response: NSURLResponse?, error: NSError?) in
...
}
task?.resume()
4. New NSURLSession API
-
Sharing Cookies
- Between Apps and Extensions
- Apps and their extensions have different cookie storages by default
- Can use application groups to get a shared data containerOS X 10.11 and iOS 9 introduce new API to create a shared cookie storage
5. New NSHTTPCookieStorage API
let ident = "group.mycompany.mygroupname"let cookieStorage = NSHTTPCookieStorage.sharedCookieStorageForGroupContainerIdentifier( identifier: ident)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()config.HTTPCookieStorage = cookieStorage
let session = NSURLSession(configuration: config)
6. NSURLSessionStreamTask
-
Asynchronous read
let task = NSURLSession.sharedSession().streamTaskWithHostName("chat.example.com", port: 5555)! task.resume() task.readDataOfMinLength(16384, maxLength:65536, timeout: 30.0) { (data: NSData?, eof: Bool, error: NSError?) in ... } let task = NSURLSession.sharedSession().streamTaskWithHostName("chat.example.com", port: 5555)! task.resume() let data: NSData = ...task.writeData(data, timeout: 30.0) { (error: NSError?) in ... }
-
Enabling TLS
let task = NSURLSession.sharedSession().streamTaskWithHostName("chat.example.com", port: 5555)! task.startSecureConnection() task.resume() let data: NSData = ...task.writeData(data, timeout: 30.0) { (error: NSError?) in ... }
-
NSStream support
let streamTask: NSURLSessionStreamTask = ... streamTask.captureStreams()
-
NSStream support
func URLSession(session: NSURLSession,streamTask: NSURLSessionStreamTask, didBecomeInputStream inputStream: NSInputStream, outputStream: NSOutputStream) { // Can pass inputStream / outputStream to APIs that consume NSStreams }
-
Other (informational) delegate methods
optional func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask)
-
Other (informational) delegate methods
optional func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTaskstreamTask: NSURLSessionStreamTask) optional func URLSession(session: NSURLSession, readClosedForStreamTask streamTask:NSURLSessionStreamTask) optional func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask:NSURLSessionStreamTask)
-
DataTask conversion
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) { completionHandler(.BecomeStream) } func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didBecomeStreamTask streamTask: NSURLSessionStreamTask) { }