我正在尝试在我的iOS应用中与公司的API通信。我正在使用标准的URLSession。
API将自动进行负载平衡并重定向到其他服务器,因此我已经实现了用于处理重定向的URLSessionDelegate和URLSessionTaskDelegate方法。
最初登录时,我将从http://our.api.com重定向到http://our1.api.com或其他版本的具有不同服务器编号的API。我第一次使用http://our1.api.com进行身份验证时,它将尊重传入的Authorization标头和质询的URLCredential。但是,如果我尝试使用已知的错误凭据再次针对相同的API进行身份验证,则会使用旧的URLCredential,并且在无法访问API时可以进入该API。
是否有一种方法可以强制URLSession 从不使用缓存的URLCredential,或者以其他方式清除缓存的URLCredentials?
创建URLSession
let config = URLSessionConfiguration.ephemeral
config.httpAdditionalHeaders = ["Accept":"application/xml",
"Accept-Language":"en",
"Content-Type":"application/xml"]
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil
self.urlSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
调用API
var request = URLRequest(url: thePreRedirectedUrl)
request.httpMethod = "GET"
request.addValue("Basic username:password", forHTTPHeaderField: "Authorization")
let task = urlSession?.dataTask(with: request, completionHandler: { (data, response, error) in
// pass endpoint results to completion block
completionBlock(data, response, error)
})
// run the task
if let task = task {
task.resume()
}
URLSessionDelegate和URLSessionTaskDelegate
extension ApiManager: URLSessionDelegate, URLSessionTaskDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.previousFailureCount == 0 {
completionHandler(.useCredential, URLCredential(user: username, password: password, persistence: .none))
} else {
completionHandler(.performDefaultHandling, nil)
}
}
func urlSession(_ session: URLSession,
task: URLSessionTask,
willPerformHTTPRedirection response: HTTPURLResponse,
newRequest request: URLRequest,
completionHandler: @escaping (URLRequest?) -> Void) {
var newRequest = URLRequest(url: request.url!)
newRequest.addValue("Basic username:password", forHTTPHeaderField: "Authorization")
newRequest.httpMethod = task.originalRequest?.httpMethod
newRequest.httpBody = task.originalRequest?.httpBody
completionHandler(newRequest)
}
}
答案 0 :(得分:0)
最可靠的方法是从用户(macOS)或应用程序(iOS)的钥匙串中删除凭据。
有关详情,请参阅Apple开发者网站上的Updating and Deleting Keychain Items,但基本上:
NSDictionary *matchingDictionary = @{
kSecClass: kSecClassInternetPassword,
kSecAttrSecurityDomain: @"example.com" // <-- This may not be quite the
// right format for the domain.
};
SecItemDelete((__bridge CFDictionaryRef) matchingDictionary);