详细解析几个和网络请求有关的类(九) —— 身份验证挑战和TLS链验证(五)

版本记录

版本号 时间
V1.0 2018.03.12

前言

我们做APP发起网络请求,一般都是使用框架,这些框架的底层也都是苹果的API,接下来几篇就一起来看一下和网络有关的几个类。感兴趣的可以看上面几篇文章。
1. 详细解析几个和网络请求有关的类 (一) —— NSURLSession
2. 详细解析几个和网络请求有关的类(二) —— NSURLRequest和NSMutableURLRequest
3. 详细解析几个和网络请求有关的类(三) —— NSURLConnection
4. 详细解析几个和网络请求有关的类(四) —— NSURLSession和NSURLConnection的区别
5. 详细解析几个和网络请求有关的类(五) —— 关于NSURL加载系统(一)
6. 详细解析几个和网络请求有关的类(六) —— 使用NSURLSession(二)
7. 详细解析几个和网络请求有关的类(七) —— URL数据的编码和解码(三)
8. 详细解析几个和网络请求有关的类(八) —— 处理重定向和其他请求更改(四)

回顾

上一篇主要介绍处理重定向和其他请求更改,这一篇主要讲述身份验证挑战和TLS链验证。


身份验证挑战和TLS链验证

NSURLRequest对象经常遇到身份验证质询,或者来自连接到的服务器的凭证请求。 NSURLSession类在请求遇到身份验证质询时通知其代理,以便它们可以相应地执行操作。

重要提示:除非服务器响应包含WWW-Authenticate标头,否则URL加载系统类不会调用其代理来处理请求质询。 其他身份验证类型(如代理身份验证和TLS信任验证)不需要此标头。


Deciding How to Respond to an Authentication Challenge - 决定如何响应验证挑战

如果会话任务要求身份验证,并且没有可用的有效凭据(作为请求的URL的一部分或共享的NSURLCredentialStorage),则会创建身份验证质询。它首先发送URLSession:task:didReceiveChallenge:completionHandler:给它的任务代理来处理认证挑战。如果任务代理没有对该消息做出响应,则任务向其会话代理发送URLSession:task:didReceiveChallenge:completionHandler:来处理身份验证质询。

为了继续连接,代表有三个选项:

  • 提供认证凭证。
  • 尝试继续没有凭据。
  • 取消认证挑战。

为帮助确定正确的操作过程,传递给该方法的NSURLAuthenticationChallenge实例包含有关什么触发了身份验证质询,针对质询进行了多少次尝试,以前尝试的凭据,需要凭据的NSURLProtectionSpace以及发送者挑战等信息。

如果身份验证质询尝试先前进行身份验证并失败(例如,如果用户在服务器上更改了自己的密码),则可以通过对身份验证质询调用proposalCredential来获取尝试的凭据。委托人然后可以使用这些凭证来填充它向用户呈现的对话框。

在身份验证质询中调用previousFailureCount将返回之前身份验证尝试的总次数,包括来自不同身份验证协议的身份验证次数。代理可以将此信息提供给用户,以确定它先前提供的凭证是否失败,或者限制最大验证次数。


Responding to an Authentication Challenge - 应对认证挑战

以下是您可以响应代理方法:URLSession:didReceiveChallenge:completionHandler:URLSession:task:didReceiveChallenge:completionHandler:的三种方式。

1. Providing Credentials - 提供凭证

要尝试进行身份验证,应用程序应该创建一个NSURLCredential对象,其中包含服务器期望的表单的身份验证信息。您可以通过在所提供的身份验证质询的保护空间中调用authenticationMethod来确定服务器的身份验证方法。 NSURLCredential支持的一些认证方法是:

  • HTTP基本认证(NSURLAuthenticationMethodHTTPBasic)需要用户名和密码。提示用户输入必要信息,并使用credentialWithUser:password:persistence:创建一个NSURLCredential对象。
  • HTTP摘要认证(NSURLAuthenticationMethodHTTPDigest)与基本认证一样,需要用户名和密码。 (摘要自动生成。)提示用户输入必要信息,并使用credentialWithUser:password:persistence:创建一个NSURLCredential对象。
  • 客户端证书身份验证(NSURLAuthenticationMethodClientCertificate)需要系统身份和需要向服务器进行身份验证的所有证书。使用credentialWithIdentity:certificates:persistence:创建NSURLCredential对象。
  • 服务器信任认证(NSURLAuthenticationMethodServerTrust)需要由认证挑战的保护空间提供的信任。使用credentialForTrust:创建一个NSURLCredential对象。

创建NSURLCredential对象后,使用提供的完成处理程序块将对象传递给身份验证质询发送方。

2. Continuing Without Credentials - 继续没有证书

如果代理选择不提供身份验证质询的凭证,则可以尝试在没有身份验证质询的情况下继续。 将以下值之一传递给提供的完成处理程序块:

3. Canceling the Connection - 取消连接

代理也可以选择通过将NSURLSessionAuthChallengeCancelAuthenticationChallenge传递给提供的完成处理程序块来取消认证挑战。

4. An Authentication Example - 一个认证示例

Listing 4-1所示的实现通过创建一个NSURLCredential实例来回应挑战,该实例具有应用程序首选项提供的用户名和密码。 如果之前认证失败,则取消认证质询并通知用户。

// Listing 4-1  An example of using the URLSession:didReceiveChallenge:completionHandler: delegate method

- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler
{
    if ([challenge previousFailureCount] == 0) {
        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:[self preferencesName]
                                                                    password:[self preferencesPassword]
                                                                 persistence:NSURLCredentialPersistenceNone];
        completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
    } else {
        // Inform the user that the user name and password are incorrect
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard challenge.previousFailureCount == 0 else {
        challenge.sender?.cancel(challenge)
        // Inform the user that the user name and password are incorrect
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    
    let proposedCredential = URLCredential(user: self.preferencesName, password: self.preferencesPassword, persistence: .none)
    completionHandler(.useCredential, proposedCredential)
}

如果认证挑战未被会话或任务代理处理,并且凭证不可用或者未通过身份验证,则基础实现将发送continueWithoutCredentialForAuthenticationChallenge:消息。


Performing Custom TLS Chain Validation - 执行自定义TLS链验证

在NSURL系列API中,TLS链验证由应用程序的身份验证代理方法处理,但您的应用程序不是提供验证用户(或您的应用程序)到服务器的凭据,而是检查服务器在TLS握手期间提供的凭据,然后告诉URL加载系统它应该接受还是拒绝这些凭证。

如果您需要以非标准方式执行链验证(例如接受特定的自签名证书进行测试),则您的应用必须实现URLSession:didReceiveChallenge:completionHandler:URLSession:task:didReceiveChallenge:completionHandler:代理方法。如果您同时实施,则会话级别的方法负责处理身份验证。

在您的身份验证处理程序代理方法中,您应该检查以确定质询保护空间是否具有NSURLAuthenticationMethodServerTrust的身份验证类型,如果是,则从该保护空间获取serverTrust信息

后记

本篇要讲述身份验证挑战和TLS链验证,希望大家继续关注我。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容