无法在 URLSessionDelegate 中接收 NSURLAuthenticationMethodHTTPBasic
Can't receive NSURLAuthenticationMethodHTTPBasic in URLSessionDelegate
我正在尝试使用 URLSessionDelegate
和 URLCredentials
实现 basic-authentication
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void)
苹果建议不要手动编写Authorization
header。所以我正在尝试使用 URLCredentials
.
我正在 Swift 游乐场中做一个非常简单的例子:
class Callback: NSObject {}
extension Callback: URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
print("received challenge")
print(challenge.protectionSpace.authenticationMethod)
completionHandler(.performDefaultHandling, nil)
}
}
let callback = Callback()
var configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: callback, delegateQueue: nil)
let string = "http://demo0230490.mockable.io/test"
var request = URLRequest(url: URL(string: string)!)
session.dataTask(with: request) { (data, response, error) in
print("response")
print(response)
}.resume()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
问题是 – 我没有收到身份验证挑战。
如果您在浏览器中转到 http://demo0230490.mockable.io/test
,您将看到浏览器显示基本身份验证警报。
从我的模拟 http 我 return header 喜欢:
"Www-Authenticate" = (
"Basic realm=\"Access to MRM\""
);
我还尝试切换到 https
(我的意思是 https://demo0230490.mockable.io/test
)来检查我是否会收到 NSURLAuthenticationMethodServerTrust
类型的身份验证质询。
那行得通。这意味着我的 delegate
已正确设置并且在某些情况下可以正常工作。
所以问题是:
任何人都可以指出问题或使用 URLCredentials
(例如使用 https://www.mockable.io)提供基本身份验证的工作示例吗?
您应该使用 urlSession(_:task:didReceive:completionHandler:)
个 URLSessionTaskDelegate
。您使用的方法是针对连接级别的挑战,而不是针对应用级别的挑战。
根据documentation urlSession(_:didReceive:completionHandler:)
只在两种情况下被调用:
- When a remote server asks for client certificates or Windows NT LAN Manager (NTLM) authentication, to allow your app to provide
appropriate credentials
- When a session first establishes a connection to a remote server that uses SSL or TLS, to allow your app to verify the server’s
certificate chain
当您切换到 https 时,满足第二个条件,因此调用方法。
身份验证质询有两种类型:会话级和非会话级。
对于非会话级别的挑战,URLSession 调用 urlSession(_:task:didReceive:completionHandler:)
。对于会话级别的挑战,URLSession 调用 urlSession(_:didReceive:completionHandler:)
.
会话级别挑战和非会话级别挑战之间的区别在 urlSession(_:task:didReceive:completionHandler:)
documentation 的讨论部分进行了描述:
For session-level challenges—NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate,
NSURLAuthenticationMethodClientCertificate, or
NSURLAuthenticationMethodServerTrust—the NSURLSession object calls the
session delegate’s urlSession(:didReceive:completionHandler:) method.
If your app does not provide a session delegate method, the
NSURLSession object calls the task delegate’s
urlSession(:task:didReceive:completionHandler:) method to handle the
challenge.
For non-session-level challenges (all others), the URLSession object calls the session delegate’s
urlSession(:task:didReceive:completionHandler:) method to handle the
challenge. If your app provides a session delegate and you need to
handle authentication, then you must either handle the authentication
at the task level or provide a task-level handler that calls the
per-session handler explicitly. The session delegate’s
urlSession(:didReceive:completionHandler:) method is not called for
non-session-level challenges.
在您的情况下,您应该实施非会话级质询处理程序:
extension Callback: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("received task challenge")
}
}
Apple-forum 上也有工作示例。
我正在尝试使用 URLSessionDelegate
和 URLCredentials
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void)
苹果建议不要手动编写Authorization
header。所以我正在尝试使用 URLCredentials
.
我正在 Swift 游乐场中做一个非常简单的例子:
class Callback: NSObject {}
extension Callback: URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
print("received challenge")
print(challenge.protectionSpace.authenticationMethod)
completionHandler(.performDefaultHandling, nil)
}
}
let callback = Callback()
var configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: callback, delegateQueue: nil)
let string = "http://demo0230490.mockable.io/test"
var request = URLRequest(url: URL(string: string)!)
session.dataTask(with: request) { (data, response, error) in
print("response")
print(response)
}.resume()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
问题是 – 我没有收到身份验证挑战。
如果您在浏览器中转到 http://demo0230490.mockable.io/test
,您将看到浏览器显示基本身份验证警报。
从我的模拟 http 我 return header 喜欢:
"Www-Authenticate" = (
"Basic realm=\"Access to MRM\""
);
我还尝试切换到 https
(我的意思是 https://demo0230490.mockable.io/test
)来检查我是否会收到 NSURLAuthenticationMethodServerTrust
类型的身份验证质询。
那行得通。这意味着我的 delegate
已正确设置并且在某些情况下可以正常工作。
所以问题是:
任何人都可以指出问题或使用 URLCredentials
(例如使用 https://www.mockable.io)提供基本身份验证的工作示例吗?
您应该使用 urlSession(_:task:didReceive:completionHandler:)
个 URLSessionTaskDelegate
。您使用的方法是针对连接级别的挑战,而不是针对应用级别的挑战。
根据documentation urlSession(_:didReceive:completionHandler:)
只在两种情况下被调用:
- When a remote server asks for client certificates or Windows NT LAN Manager (NTLM) authentication, to allow your app to provide appropriate credentials
- When a session first establishes a connection to a remote server that uses SSL or TLS, to allow your app to verify the server’s certificate chain
当您切换到 https 时,满足第二个条件,因此调用方法。
身份验证质询有两种类型:会话级和非会话级。
对于非会话级别的挑战,URLSession 调用 urlSession(_:task:didReceive:completionHandler:)
。对于会话级别的挑战,URLSession 调用 urlSession(_:didReceive:completionHandler:)
.
会话级别挑战和非会话级别挑战之间的区别在 urlSession(_:task:didReceive:completionHandler:)
documentation 的讨论部分进行了描述:
For session-level challenges—NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate, or NSURLAuthenticationMethodServerTrust—the NSURLSession object calls the session delegate’s urlSession(:didReceive:completionHandler:) method. If your app does not provide a session delegate method, the NSURLSession object calls the task delegate’s urlSession(:task:didReceive:completionHandler:) method to handle the challenge.
For non-session-level challenges (all others), the URLSession object calls the session delegate’s urlSession(:task:didReceive:completionHandler:) method to handle the challenge. If your app provides a session delegate and you need to handle authentication, then you must either handle the authentication at the task level or provide a task-level handler that calls the per-session handler explicitly. The session delegate’s urlSession(:didReceive:completionHandler:) method is not called for non-session-level challenges.
在您的情况下,您应该实施非会话级质询处理程序:
extension Callback: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("received task challenge")
}
}
Apple-forum 上也有工作示例。