我正在使用此自定义类使用证书从服务器(ASP.NET IIS 7.5)下载数据。它工作得很好,除了每次请求都会调用didReceiveChallenge方法,并且必须一次又一次地应用凭证。表现很糟糕。
我们怎样才能避免这种情况?
感谢。
#import "ServerRequest.h"
#import <UIKit/UIKit.h>
@implementation ServerRequest{
NSMutableData * recievedData;
NSString * operationName;
NSString * operationParameters;
DataOperationType operationType;
NSURL* downloadURL;
NSData * HTTPBodyData;
UIView * waitView;
UIProgressView * progressView;
}
- (instancetype)init{
if(self = [super init]) {
}
return self;
}
- (NSURLSession *)normalSession{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLProtectionSpace * protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[Config getBaseURL] port:443 protocol:@"https" realm:nil authenticationMethod:NSURLAuthenticationMethodClientCertificate];
[configuration.URLCredentialStorage setDefaultCredential:[Helper getCredential] forProtectionSpace:protectionSpace];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
return session;
}
- (instancetype)initWithRequest:(NSString *)request
{
if(self = [super init]) {
operationType = DataOperationTypeData;
downloadURL = [NSURL URLWithString:request];
NSLog(@"Created download operation for URL: %@", [downloadURL absoluteString]);
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request Dicionary:(NSString *) dataDictionary{
if(self = [super init]) {
operationType = DataOperationTypeHTMLFrom;
downloadURL = [NSURL URLWithString:request];
NSLog(@"Created download operation for URL: %@", [downloadURL absoluteString]);
operationParameters = dataDictionary;
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request data:(NSData *) bodyData{
if(self = [super init]) {
operationType = DataOperationTypeBodyData;
downloadURL = [NSURL URLWithString:request];
NSLog(@"Created download operation for URL: %@", [downloadURL absoluteString]);
HTTPBodyData = bodyData;
}
return self;
}
- (void) performOperationWithCompletion:(ServerRequestCompletion)onCompletion error:(ServerRequestError)onError{
if (self.showProgressView){
[self configureProgressView];
}
if (self.parentView) {
waitView = [Config createWaitView:self.parentView];
}
self.completion = onCompletion;
self.error = onError;
NSMutableURLRequest *request;
request = [NSMutableURLRequest requestWithURL:downloadURL];
[request setHTTPMethod:@"POST"];
[request setValue:@"utf-8" forHTTPHeaderField:@"Accept-Charset"];
if (operationType == DataOperationTypeHTMLFrom) {
NSData *postData = [operationParameters dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:@"POST"];
[request setValue:@"utf-8" forHTTPHeaderField:@"Accept-Charset"];
[request setValue:[NSString stringWithFormat:@"%ld", (unsigned long)postData.length] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
}
else if (operationType == DataOperationTypeBodyData) {
[request setHTTPMethod:@"POST"];
[request setValue:[NSString stringWithFormat:@"%ld", (unsigned long)HTTPBodyData.length] forHTTPHeaderField:@"Content-Length"];
[request addValue: @"multipart/form-data; charset=utf-8" forHTTPHeaderField: @"Content-Type"];
[request setHTTPBody:HTTPBodyData];
}
else{
[request setValue:@"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:@"Content-Type"];
}
NSURLSession * defaultSession = [self normalSession];
NSURLSessionTask * dataTask = [defaultSession dataTaskWithRequest:request];
if (!dataTask) {
self.error([EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Could not initialize connection"}]);
}else{
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setHidden:NO];
// [appDelegate.progressView setProgress:0];
});
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[dataTask resume];
}
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler{
//NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
NSURLCredential *credential = [Helper getCredential];
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
{
if (challenge.previousFailureCount >= 3)
{
// handle the fact that the previous attempt failed
EXError* error = [EXError errorWithDomain:NSURLErrorDomain code:403 userInfo: @{NSLocalizedDescriptionKey: @"Unable to verify account information."}];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
self.error(error);
}else{
NSURLCredentialPersistence persistence = NSURLCredentialPersistenceForSession;
NSString * userName = [Config getUserName];
NSString * password = [Config getPassword];
NSURLCredential *loginCredential = [NSURLCredential credentialWithUser:userName password:password persistence:persistence];
completionHandler(NSURLSessionAuthChallengeUseCredential, loginCredential);
[self removeWaitView];
}
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
//completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
{ NSLog(@"\n______________________________________________________ Authentication Method Client Certificate _________________________________________________");
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else{
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
[self removeWaitView];
}
}
-(void) configureProgressView{
UIViewController * topController = [Helper currentTopViewController];
if (![topController isKindOfClass:[UINavigationController class]]) {
return;
}
UINavigationController * navigationController = (UINavigationController *)topController;
UINavigationBar * navigationBar = [navigationController navigationBar];
progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressView.frame = CGRectMake(navigationBar.frame.origin.x, navigationBar.frame.size.height - 5, navigationBar.frame.size.width, 5);
[navigationBar addSubview:progressView];
}
-(void) removeWaitView{
[waitView removeFromSuperview];
waitView = nil;
}
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error{
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSDictionary *responseHeaders = ((NSHTTPURLResponse *)response).allHeaderFields;
NSLog(@"headers: %@", responseHeaders.description);
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= 400) { // Client/Server Error
EXError * error = [EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:httpResponse.statusCode userInfo:@{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]}];
self.error(error);
NSLog(@"Failed with Error %ld : %@", (long)httpResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]);
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
return;
}
}
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
if (!recievedData) {
recievedData = [NSMutableData new];
}
[recievedData appendData:data];
if ([dataTask countOfBytesExpectedToReceive] !=NSURLSessionTransferSizeUnknown) {
double progress = (double)[dataTask countOfBytesReceived] / (double) [dataTask countOfBytesExpectedToReceive];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:progress animated:YES];
});
}
}
// DLog(@"progress : %lld", [dataTask countOfBytesExpectedToReceive]);
}
//- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
// didSendBodyData:(int64_t)bytesSent
// totalBytesSent:(int64_t)totalBytesSent
// totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
// // DLog(@"Did Sent %f", (double)totalBytesSent);
//
// if (self.showProgressView) {
//
// dispatch_async(dispatch_get_main_queue(), ^{
//
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setProgress:
// (double)totalBytesSent /
// (double)totalBytesExpectedToSend animated:YES];
//
// });
// }
//}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setHidden:YES];
});
}
// NSString *myString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// NSLog(@"%@", myString);
if(error == nil)
{
// SBJSON *json = [SBJSON new];
// NSString *responseString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// //NSLog(@"Finished (%@) %d bytes. %@", [downloadURL absoluteString], [data length], responseString);
//
// NSDictionary *dataSet = [json objectWithString:responseString];
NSDictionary* dataSet = [NSJSONSerialization
JSONObjectWithData:recievedData
options:kNilOptions
error:&error];
self.completion(dataSet);
}
else{
// if (error.code == -999) {
// return;
// }
// NSString * httpBody = [[NSString alloc] initWithData:task.currentRequest.HTTPBody encoding:NSUTF8StringEncoding];
//
// httpBody = [NSString stringWithFormat:@"%s\n%@", __PRETTY_FUNCTION__, httpBody];
// [Helper MsgBox:httpBody];
EXError * exError = [EXError errorWithDomain:error.domain code:error.code userInfo:@{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:error.code]}];
self.error(exError);
// DLog(@"Error %@", [error localizedDescription]);
}
}
@end
答案 0 :(得分:0)
原因之一可能是对HTTPS证书的检查。
此实例包含一个protectionSpace属性,该属性的authenticationMethod属性指示发出的质询类型(例如,对用户名和密码的请求或客户端证书)。您可以使用此值来确定是否可以应对挑战。
添加此前提条件可以检查身份验证方法并调用处理程序。
let JSONDATA =
{
data: [
{
name: "cnt",
level: "12"
},
{
name: "stewart",
level: "6"
},
{
name: "nic",
level: "7"
}
]
}
let { data } = JSONDATA;
data.map((obj)=>{
console.log(obj)
})
您可以找到身份验证方法常量here