我想知道是否有人可以帮助我了解如何将SSL证书处理添加到同步 连接到https服务。
我知道如何使用异步连接但不是同步连接。
NSString *URLpath = @"https://mydomain.com/";
NSURL *myURL = [[NSURL alloc] initWithString:URLpath];
NSMutableURLRequest *myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[myURL release];
[myURLRequest setHTTPMethod:@"POST"];
NSString *httpBodystr = @"setting1=1";
[myURLRequest setHTTPBody:[httpBodystr dataUsingEncoding:NSUTF8StringEncoding]];
NSHTTPURLResponse* myURLResponse;
NSError* myError;
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest returningResponse:&myURLResponse error:&myError];
//I guess I am meant to put some SSL handling code here
谢谢。
答案 0 :(得分:7)
使用静态sendSynchronousRequest函数是不可行的,但我找到了另一种选择。
首先 NSURLConnectionDataDelegate 这样的对象
FailCertificateDelegate.h
@interface FailCertificateDelegate : NSObject <NSURLConnectionDataDelegate>
@property(atomic,retain)NSCondition *downloaded;
@property(nonatomic,retain)NSData *dataDownloaded;
-(NSData *)getData;
@end
FailCertificateDelegate.m
#import "FailCertificateDelegate.h"
@implementation FailCertificateDelegate
@synthesize dataDownloaded,downloaded;
-(id)init{
self = [super init];
if (self){
dataDownloaded=nil;
downloaded=[[NSCondition alloc] init];
}
return self;
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace {
NSLog(@"canAuthenticateAgainstProtectionSpace:");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
NSLog(@"didReceiveAuthenticationChallenge:");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[downloaded signal];
[downloaded unlock];
self.hasFinnishLoading = YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[dataDownloaded appendData:data];
[downloaded lock];
}
-(NSData *)getData{
if (!self.hasFinnishLoading){
[downloaded lock];
[downloaded wait];
[downloaded unlock];
}
return dataDownloaded;
}
@end
使用它
FailCertificateDelegate *fcd=[[FailCertificateDelegate alloc] init];
NSURLConnection *c=[[NSURLConnection alloc] initWithRequest:request delegate:fcd startImmediately:NO];
[c setDelegateQueue:[[NSOperationQueue alloc] init]];
[c start];
NSData *d=[fcd getData];
现在您将获得使用nsurlconnection的异步使用和简单同步连接的好处的所有好处,该线程将被阻止,直到您下载委托上的所有数据,但您可以改进它在FailCertificateDelegate类上添加一些错误控制
编辑:修复大数据。基于Nikolay DS的评论。非常感谢
答案 1 :(得分:-1)
我有类似的问题。在我的情况下,我有一个同步连接使用ssl根据需要使用两个委托方法,允许我接受任何证书:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
但我仍然坚持以同步的方式做同样的事情。我在网上搜索,直到找到你的帖子,不幸的是另一个stackoverflow post暗示你不能在NSURLConnection上执行同步调用并使用ssl(因为缺少委托来处理ssl身份验证过程)。 我最终做的是获得ASIHTTPRequest并使用它。这样做很轻松,花了我一个小时的时间来完成它的工作。这是我如何使用它。
+ (NSString *) getSynchronously:(NSDictionary *)parameters {
NSURL *url = [NSURL URLWithString:@"https://localhost:8443/MyApp/";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *parameterJSONString = [parameters JSONRepresentation];
[request appendPostString:parameterJSONString];
[request addRequestHeader:@"User-Agent" value:@"MyAgent"];
request.timeOutSeconds = CONNECTION_TIME_OUT_INTERVAL;
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
NSString *responseString = [request responseString];
if (request.error) {
NSLog(@"Server connection failed: %@", [request.error localizedDescription]);
} else {
NSLog(@"Server response: %@", responseString);
}
return responseString;
}
当然重要的部分是
[request setValidatesSecureCertificate:NO];
另一个替代方法是使用上述两种方法在另一个具有a-synch连接的线程中处理下载,并阻止您希望同步连接的线程,直到请求完成为止
答案 2 :(得分:-2)
我很接近使用下面的代码找到解决方案。这有效,但经常崩溃 可能是因为我在编写代码的方式上做错了,而且我对使用的方法没有很强的理解。但是,如果有人对如何改善这一点有任何建议 请发帖。
紧接着这一行:
NSError* myError;
就在行前:
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest
returningResponse:&myURLResponse error:&myError];
添加:
int failureCount = 0;
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"mydomain.com" port:443 protocol:@"https" realm:nil
authenticationMethod:NSURLAuthenticationMethodServerTrust];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:myURL MIMEType:@"text/html"
expectedContentLength:-1 textEncodingName:nil];
NSURLAuthenticationChallenge *challange = [[NSURLAuthenticationChallenge alloc]
initWithProtectionSpace:protectionSpace proposedCredential:[NSURLCredential
credentialForTrust:protectionSpace.serverTrust] previousFailureCount:failureCount
failureResponse:response error:myError sender:nil];