ios - valido - NSURLSession+servidor con certificado autofirmado
no se pudo verificar el certificado del servidor mac (2)
Tengo una aplicación que es de producción junto con un servidor de desarrollo que tiene un certificado autofirmado.
Estoy intentando probar la 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
puedo evitarlo 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 con 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 permitiera 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
Lo 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.
No hay suficiente información para sugerir una solución concreta a su problema.
Aquí hay algunos requisitos principales:
Como desea realizar una tarea en segundo plano, asegúrese de haber creado un objeto
NSSession
adecuado a través debackgroundSessionConfiguration:
El uso de este método de fábrica de clase es obligatorio para obtener sesiones de fondo .Para las solicitudes que se ejecutan en segundo plano en un proceso separado, solo se admiten las tareas de carga y descarga . Tenga en cuenta que, en su código original, está utilizando una tarea de datos .
Asegúrese de haber implementado correctamente la aplicación del método de delegado
application:handleEventsForBackgroundURLSession:completionHandler:
en su delegado de aplicación. Cuando su aplicación no se está ejecutando, y cuando la sesión se está ejecutando en su propio proceso y requiere credenciales, iOS reiniciará su aplicación en segundo plano y la sesión de fondo llamará a este método de 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
Desactivar la evaluación de confianza del servidor debería funcionar como lo intentó en su primer ejemplo. ¡Usa esto solo para desarrollo!
Para mí tu primer ejemplo está funcionando bien. He probado 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
Actualización: esta es la interfaz de clase, la clase SessionTest es NSURLSessionDataDelegate, para iniciar la descarga de datos, cree un objeto SessionTest y llame al método startSession.
@interface SessionTest : NSObject <NSURLSessionDelegate>
- (void) startSession;
@end