Кэширование учетных данных URLSession, разрешающее аутентификацию с неверными учетными данными
Я пытаюсь связаться с API моей компании в приложении для iOS. Я использую стандартный URLSession.
API автоматически загрузит баланс и перенаправит на другой сервер, поэтому я реализовал методы URLSessionDelegate и URLSessionTaskDelegate, которые обрабатывают перенаправления.
При первом входе в систему я буду перенаправлен с http://our.api.com/ на http://our1.api.com/ или на другую версию API с другим номером сервера. В первый раз, когда я аутентифицируюсь с http://our1.api.com/ он будет учитывать переданный в заголовке авторизации и вызов URLCredential. Но если я попытаюсь снова выполнить аутентификацию на том же API с известными неверными учетными данными, будет использоваться старый URLCredential, и я смогу войти в 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)
}
}
1 ответ
Самый надежный способ - удалить учетные данные из цепочки для ключей пользователя (macOS) или приложения (iOS).
Подробности смотрите в разделе Обновление и удаление элементов цепочки для ключей на веб-сайте Apple для разработчиков, но в основном:
NSDictionary *matchingDictionary = @{
kSecClass: kSecClassInternetPassword,
kSecAttrSecurityDomain: @"example.com" // <-- This may not be quite the
// right format for the domain.
};
SecItemDelete((__bridge CFDictionaryRef) matchingDictionary);