iPhone 上的同步 SSL 证书处理

发布于 2024-09-15 17:52:08 字数 865 浏览 5 评论 0原文

我想知道是否有人可以帮助我了解如何将 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

谢谢。

I was wondering if anyone can help me understand how to add SSL certificate handling to synchronous
connections to a https service.

I know how to do this with asynchronous connections but not synchronous.

                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

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

玩心态 2024-09-22 17:52:12

我即将通过下面的代码找到解决方案。这可以工作,但经常崩溃
可能是因为我在编码的方式上做错了,而且我对所使用的方法没有深入的理解。但如果有人对如何改进这个有任何建议
请发帖。

在行:之后

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];

Im close to finding the solution for this with the code below. This works but often crashes
probably because I am doing something wrong in the way I code this and I don't have a strong understanding of the methods used. But if anyone has any suggestions on how to improve this
than please post.

Just after the line:

NSError* myError;

and just before the line:

NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest       
returningResponse:&myURLResponse error:&myError];

add:

    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];
空心↖ 2024-09-22 17:52:11

使用静态 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 评论。多谢

Using the static sendSynchronousRequest function is not posible, but i found an alternative.

First of all NSURLConnectionDataDelegate object like this one

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

And for use it

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];

Now you will have all benefits of have an async use of nsurlconnection and benefits of a simple sync connection, the thread will be blocked until you download all data on the delegate, but you could improve it adding some error control on FailCertificateDelegate class

EDIT: fix for big data. based on Nikolay DS comment. Thanks a lot

几度春秋 2024-09-22 17:52:11

我有类似的问题。就我而言,我有一个异步连接,根据需要使用 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 帖子 暗示了这一点您无法在 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];

您的另一种选择是使用上述两种方法在具有异步连接的另一个线程中处理下载,并阻止您想要同步连接的线程,直到请求完成

I had a similar issue. In my case i had an a-synchronous connection working with ssl as required using the two delegate methods that allowed me to accept any certificate:

- (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];
}

But i was stuck on doing the same in a synchronous manner. I searched the web until i found your post and unfortunately another stackoverflow post where it is hinted that you cannot perform synch calls on NSURLConnection and work with ssl (because of the lack of a delegate to handle the ssl authentication process).
What i ended up doing is getting ASIHTTPRequest and using that. It was painless to do and took me about an hour to set up and its working perfectly. here is how i use it.

+ (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;
}

The important part of course is the

[request setValidatesSecureCertificate:NO];

Another alternative for you is to handle the download in another thread with an a-synch connection using the two methods above and block the thread from which you want the synch connection until the request is complete

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文