6

我正在使用的后端 API 要求每个请求都发送一个令牌,以针对Authorization 这种格式的 HTTP 标头键 - Token xxxxxxxxxx.

现在,我正在做以下事情。

var getRequest = URLRequest(url: url)
getRequest.addValue("Token xxxxxxxx", forHTTPHeaderField: "Authorization")

这有时会起作用,有时会Authorization在发出请求时剥离标头字段。我使用查尔斯代理检查了这一点。

Apple 的文档说明了以下内容。

NSURLSession 对象旨在为您处理 HTTP 协议的各个方面。因此,您不应修改以下标头:授权、连接、主机、WWW-Authenticate

作为解决方案,许多人建议使用didReceiveAuthenticationChallengeURLSession 的委托方法。

在这里,您需要传递一个URLSession.AuthChallengeDisposition实例来说明您希望如何响应质询,并传递一个URLCredential实例来传递凭据以响应身份验证质询。

我不知道如何以及是否可以创建一个将为标题字段URLCredential添加的实例。Token xxxxxxxxAuthorization

有知识的人可以帮我解决这个问题吗?

PS - 这个问题中提到的所有代码都在 Swift 3 中。 这个问题问的问题与我所拥有的类似。但是,那里给出的答案对我不起作用。而且,在有关 Apple 不允许Authorization添加标题的问题下提出的一些问题没有得到解答。

编辑:

贴出相关代码。

var getRequest = URLRequest(url: url)
getRequest.httpMethod = "GET"
getRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
getRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let token = DataProvider.sharedInstance.token
getRequest.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
let getTask = URLSession.shared.dataTask(with: getRequest) { (data, response, error) in
        if let data = data {
            print("--------GET REQUEST RESPONSE START--------")
            print("CODE: \((response as? HTTPURLResponse)?.statusCode ?? 0)")
            print("Response Data:")
            print(String(data: data, encoding: .utf8) ?? "")
            print("--------GET REQUEST RESPONSE END--------")
        }
}
getTask.resume()

在这里,我可以确认“授权”的标头字段已添加到请求的标头字典中。

但是,当我检查服务器上的请求时,缺少“授权”的标头字段。有什么想法吗?

4

1 回答 1

10

我遇到了同样的问题,发现我缺少尾部斜杠 ,/是问题所在。

服务器正在发回301 Redirect响应。URLSession自动跟随重定向,但也会删除Authorization标题。这很可能是由于Authorization的“特殊身份”。根据URLSessionConfiguration文档

URLSession 对象旨在为您处理 HTTP 协议的各个方面。因此,您不应修改以下标头:

  • 授权
  • 联系
  • 主持人
  • WWW-认证

如果Authorization需要标头,请urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)URLSessionTaskDelegate. 该方法在重定向时传递新请求,允许您添加回标头。

例如

class APIClient: URLSessionTaskDelegate {
    let session: URLSession!
    initializeSession() {
        // Create a new session with APIClient as the delegate
        session = URLSession(configuration: URLSessionConfiguration.default,
                             delegate: self,
                             delegateQueue: nil)
    }

    // Perform the request
    func fetchRecords(handler: () => void) {
        var request = URLRequest(url: URL(string: "http://127.0.0.1:8000/api/employee/records")!)
        request.setValue(retrieveToken(), forHTTPHeaderField: "Authorization")
        session.dataTask(with: request, completionHandler: handler).resume()
    }

    // Implement URLSessionTaskDelegate's HTTP Redirection method
    func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
        // Create a mutable copy of the new request, add the header, call completionHandler
        var newRequest = request
        newRequest.addValue(retrieveToken(), forHTTPHeaderField: "Authorization")
        completionHandler(newRequest)
    }
}

重要的提示!

盲目相信重定向是个坏主意。您应该确保您被重定向到的 URL 与原始请求的域相同。为简洁起见,我已将其从代码示例中删除。

于 2017-09-20T22:44:43.827 回答