ios NSURLSession + 带有自签名证书的服务器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20230169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NSURLSession + server with self signed cert
提问by random
I have an app that is production along with a development server that has a self signed certificate.
我有一个生产应用程序以及一个具有自签名证书的开发服务器。
I am attempting to test NSURLSession
and background downloading but can't seem to get past - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
我正在尝试测试NSURLSession
和后台下载,但似乎无法通过- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
When I use NSURLConnection
I am able to bypass it using:
当我使用时,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];
}
But I can't figure out how to get this to work with NSURLSession
>:(
但我不知道如何NSURLSession
让它与> :(
This is what I have currently (that doesn't work):
这是我目前所拥有的(不起作用):
- (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]);
}
I also tried creating a category of NSURLSession
that would allow any certificate for a host:
我还尝试创建一个NSURLSession
允许主机使用任何证书的类别:
#import "NSURLRequest+IgnoreSSL.h"
@implementation NSURLRequest (IgnoreSSL)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host {
return YES;
}
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host {}
@end
Which also doesn't seem to help.
这似乎也没有帮助。
EDIT
编辑
I've updated this method to return:
我已更新此方法以返回:
- (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);
}
Which still does nothing.
仍然什么都不做。
回答by osanoj
For me your first example is working fine. I have tested with the following code without problems (it is of course very insecure since it allows any server certificate).
对我来说,你的第一个例子工作正常。我已经使用以下代码进行了测试,没有出现问题(它当然非常不安全,因为它允许任何服务器证书)。
@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
Update: This is the class interface, the SessionTest class is the NSURLSessionDataDelegate, to start the data download you create a SessionTest object and call the startSession method.
更新:这是类接口,SessionTest 类是 NSURLSessionDataDelegate,要开始数据下载,您可以创建一个 SessionTest 对象并调用 startSession 方法。
@interface SessionTest : NSObject <NSURLSessionDelegate>
- (void) startSession;
@end
回答by CouchDeveloper
There's not enough information to suggest a concrete solution to your problem.
没有足够的信息来为您的问题提出具体的解决方案。
Here are some principal requirements:
以下是一些主要要求:
Since you want a background task, ensure you created a suitable
NSSession
object throughbackgroundSessionConfiguration:
. Using this class factory method is mandatory for getting background sessions.For requests running in the background in a separate process, only uploadand downloadtasks are supported. Note that, in your original code, you are using a datatask.
Ensure you have properlyimplemented the delegate method
application:handleEventsForBackgroundURLSession:completionHandler:
in your App Delegate. When your app is not running, and when the session is running in its own process and requires credentials, iOS will restart your app in the background and the background session will call this delegate method. See also https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleEventsForBackgroundURLSession:completionHandler:
由于您需要后台任务,请确保
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:
Disabling server trust evaluation should work as you tried in your first example. Use this for development only!
禁用服务器信任评估应该像您在第一个示例中尝试的那样工作。仅用于开发!