我有一个正在制作的应用程序以及一个具有自签名证书的开发服务器。
我正在尝试测试NSURLSession
和后台下载但似乎无法超越- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
当我使用NSURLConnection
时,我可以使用以下方法绕过它:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(@"canAuthenticateAgainstProtectionSpace %@", [protectionSpace authenticationMethod]);
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"didReceiveAuthenticationChallenge %@ %zd", [[challenge protectionSpace] authenticationMethod], (ssize_t) [challenge previousFailureCount]);
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
但我无法弄明白如何使用NSURLSession
> :(
这是我目前的(不起作用):
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
NSLog(@"NSURLSession did receive challenge.");
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
我还尝试创建一个允许主机证书的NSURLSession
类别:
#import "NSURLRequest+IgnoreSSL.h"
@implementation NSURLRequest (IgnoreSSL)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host {
return YES;
}
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host {}
@end
这似乎也没有帮助。
修改
我已更新此方法以返回:
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
//Creates credentials for logged in user (username/pass)
NSURLCredential *cred = [[AuthController sharedController] userCredentials];
completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
}
哪个仍然无效。
答案 0 :(得分:39)
对我来说,你的第一个例子是正常的。我已经使用以下代码进行了测试而没有任何问题(因为它允许任何服务器证书,因此它当然非常不安全)。
@implementation SessionTest
- (void) startSession
{
NSURL *url = [NSURL URLWithString:@"https://self-signed.server.url"];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(@"Data: %@",text);
}
else
{
NSLog(@"Error: %@", error);
}
}];
[dataTask resume];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
@end
更新:这是类接口,SessionTest类是NSURLSessionDataDelegate,启动数据下载后创建一个SessionTest对象并调用startSession方法。
@interface SessionTest : NSObject <NSURLSessionDelegate>
- (void) startSession;
@end
答案 1 :(得分:1)
没有足够的信息来建议您解决问题的具体方法。
以下是一些主要要求:
由于您需要后台任务,请确保通过NSSession
创建了合适的backgroundSessionConfiguration:
对象。使用此类工厂方法对于获取后台会话是必需的。
对于在单独进程中在后台运行的请求,仅支持上载和下载任务。请注意,在原始代码中,您使用的是数据任务。
确保正确在App Delegate中实施委托方法application:handleEventsForBackgroundURLSession:completionHandler:
。当您的应用程序未运行,并且会话在其自己的进程中运行并需要凭据时,iOS将在后台重新启动您的应用程序,后台会话将调用此委托方法。另请参阅https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleEventsForBackgroundURLSession:completionHandler:
禁用服务器信任评估应该像您在第一个示例中尝试的那样工作。 仅用于开发!