【问题标题】:Difference between NSURLSession on iOS 8 and iOS 9?iOS 8 和 iOS 9 上的 NSURLSession 的区别?
【发布时间】:2015-09-18 15:09:00
【问题描述】:

我有以下代码向 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。不幸的是,我无法访问服务器以查看它实际接收的内容,并且它位于内部网络上,因此我无法链接到服务器。它使用 HTTP 基本访问身份验证,因此我假设它应该与具有该身份验证类型的任何其他服务器相同。

从 iOS 8 到 9 的 API 是否有任何可能导致此类问题的更改?例如,是否可以更改/删除/添加其他默认标头,如内容类型或用户代理?

编辑: 在使用 requests.in 进行测试后,我发现通过添加 Content-Type,这是 iOS 8 中标头的一部分,但在 iOS 9 中不是。在 iOS 8 中,我仍然可以在不设置 Content-Type 的情况下通过请求,但在 iOS 9 请求中不存在它仍然很奇怪。

【问题讨论】:

  • 这可能是个问题App Transport Security
  • 不幸的是,我永远不会得到未经授权的 401。另外,为了确定,我在 Info.plist 中添加了一个例外。
  • 两个版本都是一样的。我还有一个 Android 应用程序可以毫无问题地向服务器进行身份验证。我仅在 iOS 9 上遇到此问题。
  • 我没有注意到除 ATS 之外的任何区别。购买你可以设置一个请求 bin url (requestb.in) 然后检查 bin 在 iOS8 和 iOS9 上收到的任何差异
  • 为什么你自己用base 64编码头部值而不是使用NSURLCredential?

标签: ios swift nsurlsession basic-authentication


【解决方案1】:

我终于想通了!事实证明,在 iOS 9 中,NSURLSessionConfiguration 的 HTTPAdditionalHeaders 属性是只读的,对它的任何更改都不会反映在当前的 NSURLSession 中。最重要的是,AuthorisationConnectionHostWWW-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() 

【讨论】:

  • 将来,您可能会考虑使用charlesproxy.com 等工具来帮助破译双向网络流量。很好的 b/c 你可以看到对话的双方,而且设置无线嗅探比wireshark.org
猜你喜欢
  • 2016-06-15
  • 2014-11-17
  • 2015-01-02
  • 1970-01-01
  • 2014-10-22
  • 2015-12-17
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
相关资源
最近更新 更多