iOS 8 和 iOS 9 上的 NSURLSession 之间的区别?
Difference between NSURLSession on iOS 8 and iOS 9?
我有以下代码来向 MediaWiki 服务器验证 iOS 应用程序:
let task = NSURLSession.sharedSession()
task.configuration.HTTPAdditionalHeaders = ["Authorization": "Basic " + base64EncodedCredentials]
task.dataTaskWithURL(url!) {(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
if data != nil {
let result = NSString(data: data!, encoding: NSUTF8StringEncoding)
if resultIsValid(result) {
//Do authentication stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
})
}.resume()
在 iOS 8 上,这非常有效,我收到了 HTTP 200 OK 响应。但是,在 iOS 9 我收到 401 未经授权。不幸的是,我无法访问服务器以查看它实际接收到的内容,而且它位于内部网络上,因此我无法 link 访问服务器。它使用 HTTP 基本访问身份验证,因此我假设它应该与具有该身份验证类型的任何其他服务器相同。
API 从 iOS 8 到 9 是否有任何可能导致此类问题的变化?例如,内容类型或用户代理等其他默认 header 可以是 changed/removed/added 吗?
编辑:
在使用 requests.in 进行测试后,我发现通过添加 Content-Type,这是 iOS 8 中 header 的一部分,而不是 iOS 9 中的一部分。在 iOS 8 中,我仍然可以在不设置 Content-Type 的情况下通过请求,但它在 iOS 9 请求中不存在仍然很奇怪。
我终于想通了!原来在 iOS 9 中 NSURLSessionConfiguration 的 HTTPAdditionalHeaders 属性 是 read-only,对其的任何更改都不会反映在当前的 NSURLSession 中。除此之外,headersAuthorisation
、Connection
、Host
、WWW-Authenticate
这四个不能修改。因此,在iOS 9中,唯一的方法就是使用quellish提出的NSURLCredential。
对于遇到同样问题的任何人,这是我用来让我的身份验证同时适用于 iOS 8 和 iOS 9 的最终代码:
let url = NSURL(string: "https://subdomain2.subdomain1.example.com")
let credential = NSURLCredential(user: username, password: password, persistence: NSURLCredentialPersistence.ForSession)
let protectionSpace = NSURLProtectionSpace(host: url!.host!, port: 443, `protocol`: url!.scheme, realm: "subdomain2.example.com", authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
NSURLCredentialStorage.sharedCredentialStorage().setCredential(credential, forProtectionSpace: protectionSpace)
let task = NSURLSession.sharedSession()
task.dataTaskWithURL(url!) {(data, response, error) in
if data != nil {
if responseIsValid(response) {
//Do authenticated stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
}.resume()
我有以下代码来向 MediaWiki 服务器验证 iOS 应用程序:
let task = NSURLSession.sharedSession()
task.configuration.HTTPAdditionalHeaders = ["Authorization": "Basic " + base64EncodedCredentials]
task.dataTaskWithURL(url!) {(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
if data != nil {
let result = NSString(data: data!, encoding: NSUTF8StringEncoding)
if resultIsValid(result) {
//Do authentication stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
})
}.resume()
在 iOS 8 上,这非常有效,我收到了 HTTP 200 OK 响应。但是,在 iOS 9 我收到 401 未经授权。不幸的是,我无法访问服务器以查看它实际接收到的内容,而且它位于内部网络上,因此我无法 link 访问服务器。它使用 HTTP 基本访问身份验证,因此我假设它应该与具有该身份验证类型的任何其他服务器相同。
API 从 iOS 8 到 9 是否有任何可能导致此类问题的变化?例如,内容类型或用户代理等其他默认 header 可以是 changed/removed/added 吗?
编辑: 在使用 requests.in 进行测试后,我发现通过添加 Content-Type,这是 iOS 8 中 header 的一部分,而不是 iOS 9 中的一部分。在 iOS 8 中,我仍然可以在不设置 Content-Type 的情况下通过请求,但它在 iOS 9 请求中不存在仍然很奇怪。
我终于想通了!原来在 iOS 9 中 NSURLSessionConfiguration 的 HTTPAdditionalHeaders 属性 是 read-only,对其的任何更改都不会反映在当前的 NSURLSession 中。除此之外,headersAuthorisation
、Connection
、Host
、WWW-Authenticate
这四个不能修改。因此,在iOS 9中,唯一的方法就是使用quellish提出的NSURLCredential。
对于遇到同样问题的任何人,这是我用来让我的身份验证同时适用于 iOS 8 和 iOS 9 的最终代码:
let url = NSURL(string: "https://subdomain2.subdomain1.example.com")
let credential = NSURLCredential(user: username, password: password, persistence: NSURLCredentialPersistence.ForSession)
let protectionSpace = NSURLProtectionSpace(host: url!.host!, port: 443, `protocol`: url!.scheme, realm: "subdomain2.example.com", authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
NSURLCredentialStorage.sharedCredentialStorage().setCredential(credential, forProtectionSpace: protectionSpace)
let task = NSURLSession.sharedSession()
task.dataTaskWithURL(url!) {(data, response, error) in
if data != nil {
if responseIsValid(response) {
//Do authenticated stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
}.resume()