的iOS /可可 - NSURLSession - 处理基本HTTPS授权 [英] iOS/Cocoa - NSURLSession - Handling Basic HTTPS Authorization

查看:534
本文介绍了的iOS /可可 - NSURLSession - 处理基本HTTPS授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我不使用AFNetworking这个项目,我可能在将来这样做,但希望首先解决这个问题/误解。)

(I'm not using AFNetworking for this project. I may do so in future, but wish to resolve this problem/misunderstanding first.)

服务器设置

我不能在这里提供实实在在的服务,但它是一个简单,可靠的服务,根据这样的URL返回XML:

I cannot provide the real service here, but it is a simple, reliable service that returns XML according to a URL such as:

<一个href=\"https://username:password@example.com/webservice\">https://username:password@example.com/webservice

我想用克服HTTPS连接到的URL,并确定任何身份验证失败(HTTP状态code 401)。

I want to connect to the URL over HTTPS using GET, and determine any authentication failures (http status code 401).

我证实,Web服务是可用的,而且我可以成功(HTTP状态code 200)使用指定的用户名和密码抓住从URL XML。我这样做有网络浏览器,并与AFNetworking 2.0.3,并且通过使用NSURLConnection的。

I have confirmed that the web service is available, and that I can successfully (http status code 200) grab XML from the url using a specified username and password. I have done this with a web browser, and with AFNetworking 2.0.3, and by using NSURLConnection.

我也证实了我使用的是正确的凭据在所有阶段。

I have also confirmed that I am using the correct credentials at all stages.

由于正确的凭据及以下code:

Given the correct credentials and the the following code:

// Note: NO delegate provided here.
self.sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfig
                                  delegate:nil
                             delegateQueue:nil];

NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:self.requestURL     completionHandler: ...

以上code将工作。这将成功地连接到服务器,得到200 HTTP状态code,并返回(XML)数据。

The above code will work. It will successfully connect to the server, get a http status code of 200, and return the (XML) data.

问题1

这个简单的方法在凭证无效的情况下失败。在这种情况下,在完成块没有被调用,没有状态code(401)被提供,并最终,工作超时。

This simple approach fails in cases where the credentials are invalid. In that case, the completion block is never called, no status code (401) is provided, and eventually, the Task times out.

尝试性解决方案

我指派代表到NSURLSession,而且我办理下列回调:

I assigned a delegate to the NSURLSession, and am handling the following callbacks:

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    if (_sessionFailureCount == 0) {
        NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];        
    completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
    } else {
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
    _sessionFailureCount++;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,    NSURLCredential *credential))completionHandler
{
    if (_taskFailureCount == 0) {
        NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];        
        completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
    } else {
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
    _taskFailureCount++;
}

问题1当使用尝试性解决方案

请注意使用实例变量_sessionFailureCount和_taskFailureCount的。我使用这些,因为挑战对象的@ previousFailureCount属性永远前进!它总是保持为零,无论这些回调方法被调用多少次。

Please note the use of ivars _sessionFailureCount and _taskFailureCount. I am using these because the challenge object's @previousFailureCount property is never advanced! It always remains at zero, no matter how many times these callback methods are called.

问题2在使用尝试性解决方案

尽管使用了正确的凭据(如他们成功的使用证明了零代表),认证失败。

Despite the use of correct credentials (as proven by their successful use with a nil delegate), authentication is failing.

下面的回调出现:

URLSession:didReceiveChallenge:completionHandler:
(challenge @ previousFailureCount reports as zero)
(_sessionFailureCount reports as zero)
(completion handler is called with correct credentials)
(there is no challenge @error provided)
(there is no challenge @failureResponse provided)


URLSession:didReceiveChallenge:completionHandler:
(challenge @ previousFailureCount reports as **zero**!!)
(_sessionFailureCount reports as one)
(completion handler is called with request to cancel challenge)
(there is no challenge @error provided)
(there is no challenge @failureResponse provided)

// Finally, the Data Task's completion handler is then called on us.
(the http status code is reported as zero)
(the NSError is reported as NSURLErrorDomain Code=-999 "cancelled")

(该NSError还提供了一个NSErrorFailingURLKey,这说明我的URL和凭据是正确的。)

(The NSError also provides a NSErrorFailingURLKey, which shows me that the URL and credentials are correct.)

任何建议表示欢迎!

推荐答案

您并不需要实现这样的委托方法,简单地设置在请求授权HTTP标头,例如。

You don't need to implement a delegate method for this, simply set the authorization HTTP header on the request, e.g.

NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://whatever.com"]];

NSString *authStr = @"username:password";
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat: @"Basic %@",[authData base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:@"Authorization"];

//create the task
NSURLSessionDataTask* task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

 }];

这篇关于的iOS /可可 - NSURLSession - 处理基本HTTPS授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆