NSURLSession + server with self signed cert

谁说我不能喝 提交于 2019-11-30 10:46:42

问题


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

When I use NSURLConnection I am able to bypass it using:

- (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 >:(

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:

#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.


回答1:


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.

@interface SessionTest : NSObject <NSURLSessionDelegate>

- (void) startSession;

@end



回答2:


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 through backgroundSessionConfiguration:. Using this class factory method is mandatory for getting background sessions.

  • For requests running in the background in a separate process, only upload and download tasks are supported. Note that, in your original code, you are using a data task.

  • Ensure you have properly implemented 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:

Disabling server trust evaluation should work as you tried in your first example. Use this for development only!

See also (https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44)



来源:https://stackoverflow.com/questions/20230169/nsurlsession-server-with-self-signed-cert

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!