Servidor NSURLSession + con certificado autofirmado
Tengo una aplicación que es de producción junto con un servidor de desarrollo que tiene un certificado autofirmado .
Estoy intentando probar NSURLSession
y la descarga en segundo plano, pero parece que no puedo pasar - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
Cuando uso NSURLConnection
soy capaz de omitirlo usando:
- (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];
}
Pero no puedo averiguar cómo hacer que esto funcione NSURLSession
>:(
Esto es lo que tengo actualmente (que no funciona):
- (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]);
}
También intenté crear una categoría de NSURLSession
que permitiría cualquier certificado para un host:
#import "NSURLRequest+IgnoreSSL.h"
@implementation NSURLRequest (IgnoreSSL)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host {
return YES;
}
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host {}
@end
Que tampoco parece ayudar.
EDITAR
He actualizado este método para devolver:
- (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);
}
Que todavía no hace nada.
2 answers
Para mí tu primer ejemplo está funcionando bien. He probado con el siguiente código sin problemas (por supuesto es muy inseguro ya que permite cualquier certificado de servidor).
@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: Esta es la interfaz de clase, la clase SessionTest es la NSURLSessionDataDelegate, para iniciar la descarga de datos se crea un objeto SessionTest y se llama al método StartSession.
@interface SessionTest : NSObject <NSURLSessionDelegate>
- (void) startSession;
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-24 15:23:32
No hay suficiente información para sugerir una solución concreta a su problema.
Aquí están algunos requisitos principales:
Dado que desea una tarea en segundo plano, asegúrese de crear un objeto
NSSession
adecuado a través debackgroundSessionConfiguration:
. El uso de este método de fábrica de clase es obligatorio para obtener sesiones en segundo plano.Para las solicitudes que se ejecutan en segundo plano en un proceso separado, solo se admiten las tareas upload y download. Nota que, en su código original, está utilizando una tarea data .
Asegúrese de que ha implementado correctamente el método delegado
application:handleEventsForBackgroundURLSession:completionHandler:
en el Delegado de la aplicación. Cuando la aplicación no se está ejecutando, y cuando la sesión se está ejecutando en su propio proceso y requiere credenciales, iOS reiniciará la aplicación en segundo plano y la sesión en segundo plano llamará a este método delegado. Véase también https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleEventsForBackgroundURLSession:completionHandler:
Deshabilitar la evaluación de confianza del servidor debería funcionar como lo intentó en su primer ejemplo. Utilice esto solo para el desarrollo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-21 20:28:25