如何使用 iOS 7 的 NSURLSession 接受自签名 SSL 证书
How do I accept a self-signed SSL certificate using iOS 7's NSURLSession
我有以下代码(swift 实现):
func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool
{
return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
}
func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge)
{
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
{
if challenge.protectionSpace.host == "myDomain"
{
let credentials = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
challenge.sender.useCredential(credentials, forAuthenticationChallenge: challenge)
}
}
challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
}
它在 iOS 8.x、 中完美运行,但在 iOS 7.x 中不起作用
在 iOS 7.x 我有错误:
NSURLConnection/CFURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9813)
有什么想法吗?
谢谢你!!!
无论如何,connection:canAuthenticateAgainstProtectionSpace:
和 connection:didReceiveAuthenticationChallenge:
都在 iOS 8 中被弃用,因此您应该使用其他方法。
我在项目中使用的是NSURLSessionDelegate的委托方法。遵守该协议,然后添加此方法:
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust))
}
然后,当您使用初始化 NSURLSession 并将委托设置为 self 时。例如:
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
然后使用该会话实例调用 dataTaskWithRequest 方法:
var task = session.dataTaskWithRequest(request){
(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if error != nil {
callback("", error.localizedDescription)
} else {
var result = NSString(data: data, encoding:
NSASCIIStringEncoding)!
}
}
task.resume()
可以找到完整的工作示例 here。
出于安全原因,如果您使用自签名证书,我建议还实施 public 密钥固定 (https://gist.github.com/edwardmp/df8517aa9f1752e73353)
继承class 与 URLSessionDelegate
创建会话对象
let config = URLSessionConfiguration.default
let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: httpRequest as URLRequest, completionHandler: {requestData, response, errorData -> Void in
if errorData == nil {
dataCallback(requestData! as NSData)
}
else {
let error = NSError(domain: "Err-1001", code: 11, userInfo:nil)
failureCallback(error)
}
});
task.resume()
添加委托方法
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(
.useCredential,
URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
将此添加到您的 info.plist 文件中
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>xyc.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSRequiresCertificateTransparency</key>
<false/>
</dict>
</dict>
</dict>
Swift 5 解
注意这些设置仅用于测试目的,请勿在生产应用中推送更改
步骤
在info.plist
中的“App Transport Security Settings”下将“Allow Arbitrary Loads”键添加到“YES”
创建新的会话对象并委托给自己
让配置=URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
将 URLSessionDelegate 协议实施到当前 class
扩展名 YouClass:URLSessionDelegate{
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
}
修改版本:
我有以下代码(swift 实现):
func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool
{
return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
}
func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge)
{
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
{
if challenge.protectionSpace.host == "myDomain"
{
let credentials = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
challenge.sender.useCredential(credentials, forAuthenticationChallenge: challenge)
}
}
challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
}
它在 iOS 8.x、 中完美运行,但在 iOS 7.x 中不起作用 在 iOS 7.x 我有错误:
NSURLConnection/CFURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9813)
有什么想法吗? 谢谢你!!!
无论如何,connection:canAuthenticateAgainstProtectionSpace:
和 connection:didReceiveAuthenticationChallenge:
都在 iOS 8 中被弃用,因此您应该使用其他方法。
我在项目中使用的是NSURLSessionDelegate的委托方法。遵守该协议,然后添加此方法:
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust))
}
然后,当您使用初始化 NSURLSession 并将委托设置为 self 时。例如:
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
然后使用该会话实例调用 dataTaskWithRequest 方法:
var task = session.dataTaskWithRequest(request){
(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if error != nil {
callback("", error.localizedDescription)
} else {
var result = NSString(data: data, encoding:
NSASCIIStringEncoding)!
}
}
task.resume()
可以找到完整的工作示例 here。
出于安全原因,如果您使用自签名证书,我建议还实施 public 密钥固定 (https://gist.github.com/edwardmp/df8517aa9f1752e73353)
继承class 与 URLSessionDelegate
创建会话对象
let config = URLSessionConfiguration.default
let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: httpRequest as URLRequest, completionHandler: {requestData, response, errorData -> Void in
if errorData == nil {
dataCallback(requestData! as NSData)
}
else {
let error = NSError(domain: "Err-1001", code: 11, userInfo:nil)
failureCallback(error)
}
});
task.resume()
添加委托方法
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(
.useCredential,
URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
将此添加到您的 info.plist 文件中
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>xyc.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSRequiresCertificateTransparency</key>
<false/>
</dict>
</dict>
</dict>
Swift 5 解
注意这些设置仅用于测试目的,请勿在生产应用中推送更改
步骤
在info.plist
中的“App Transport Security Settings”下将“Allow Arbitrary Loads”键添加到“YES”创建新的会话对象并委托给自己
让配置=URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)将 URLSessionDelegate 协议实施到当前 class
扩展名 YouClass:URLSessionDelegate{ func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!)) } }
修改版本: