SDWebImage探究(十五) —— 深入研究图片下载流程(九)之身份验证质询代理方法调用

版本记录

版本号 时间
V1.0 2018.02.25

前言

我们做APP,文字和图片是绝对不可缺少的元素,特别是图片一般存储在图床里面,一般公司可以委托第三方保存,NB的公司也可以自己存储图片,ios有很多图片加载的第三方框架,其中最优秀的莫过于SDWebImage,它几乎可以满足你所有的需求,用了好几年这个框架,今天想总结一下。感兴趣的可以看其他几篇。
1. SDWebImage探究(一)
2. SDWebImage探究(二)
3. SDWebImage探究(三)
4. SDWebImage探究(四)
5. SDWebImage探究(五)
6. SDWebImage探究(六) —— 图片类型判断深入研究
7. SDWebImage探究(七) —— 深入研究图片下载流程(一)之有关option的位移枚举的说明
8. SDWebImage探究(八) —— 深入研究图片下载流程(二)之开始下载并返回下载结果的总的方法
9. SDWebImage探究(九) —— 深入研究图片下载流程(三)之下载之前的缓存查询操作
10. SDWebImage探究(十) —— 深入研究图片下载流程(四)之查询缓存后的block回调处理
11. SDWebImage探究(十一) —— 深入研究图片下载流程(五)之SDWebImageDownloadToken和操作对象的生成和返回
12. SDWebImage探究(十二) —— 深入研究图片下载流程(六)之下载器到具体下载操作的代理分发实现
13. SDWebImage探究(十三) —— 深入研究图片下载流程(七)之NSURLSession中几个代理的基本用法和关系
14. SDWebImage探究(十四) —— 深入研究图片下载流程(八)之下载完成代理方法的调用

SDWebImageDownloaderOperation中身份验证质询代理方法

该代理方法主要用于:该任务已收到请求特定的身份验证质询

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __block NSURLCredential *credential = nil;
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates)) {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        } else {
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            disposition = NSURLSessionAuthChallengeUseCredential;
        }
    } else {
        if (challenge.previousFailureCount == 0) {
            if (self.credential) {
                credential = self.credential;
                disposition = NSURLSessionAuthChallengeUseCredential;
            } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    }
    
    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}

该代理方法主要做一下几个工作:

  • 构造参数NSURLSessionAuthChallengeDisposition dispositionNSURLCredential *credential
  • 回调block completionHandler,将上面获取的参数作为输入参数传递completionHandler(disposition, credential)

disposition和credential参数的构建

1. NSURLSessionAuthChallengeDisposition枚举

NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;

首先我们要看一下NSURLSessionAuthChallengeDisposition这个枚举。首先看一下API然后在看其用法。

typedef NS_ENUM(NSInteger, NSURLSessionAuthChallengeDisposition) {
    NSURLSessionAuthChallengeUseCredential = 0,                                       
    /* Use the specified credential, which may be nil */
    //使用指定的credential,可能为nil
    
    NSURLSessionAuthChallengePerformDefaultHandling = 1,                              
    /* Default handling for the challenge - as if this delegate were not implemented; the credential parameter is ignored. */
    //挑战challenge的默认处理 - 就好像这个代理没有实现,凭证credential参数被忽略
    
    NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,                      
    /* The entire request will be canceled; the credential parameter is ignored. */
    // 整个的请求将被取消,忽略credential参数。
    
    NSURLSessionAuthChallengeRejectProtectionSpace = 3,                               
    /* This challenge is rejected and the next authentication protection space should be tried; the credential parameter is ignored. */
    //这个挑战被拒绝,并且应该尝试下一个认证保护空间; 凭证credential参数被忽略
} NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);

这里其实就是用来进行身份验证的,这个和HTTP还有HTTPS有关,大家都知道HTTPS更安全,很多国际大公司都提倡使用HTTPS。下面两张图可以很明显的说明二者的区别,图片来源网络,后面已经增加引用参考说明。

从上面可以看见,由于增加受保护空间以及公钥的加密,信息在相对更安全的路径进行传输。

下面回到SDWebImage中,处理方式disposition首先默认取值NSURLSessionAuthChallengePerformDefaultHandling,这个的意思就是使用默认方式进行处理,其实这就相当于一个变量的初始化。

2. if条件判断

if条件判断主要对应下面这一小段代码。

if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
    if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates)) {
        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    }
    else {
        credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        disposition = NSURLSessionAuthChallengeUseCredential;
    }
}

首先看一下判断条件[challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]

/*!
    @const NSURLAuthenticationMethodServerTrust
    @abstract SecTrustRef validation required.  Applies to any protocol.
 */
FOUNDATION_EXPORT NSString * const NSURLAuthenticationMethodServerTrust API_AVAILABLE(macos(10.6), ios(3.0), watchos(2.0), tvos(9.0));

这个判断条件的作用就是判断服务器返回的证书是否是服务器信任的。

如果是信任的,接着进行判断,如果options不是SDWebImageDownloaderAllowInvalidSSLCertificates

/**
 * Enable to allow untrusted SSL certificates.
 * Useful for testing purposes. Use with caution in production.
 */
SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,

也就是不允许无效的证书,那么disposition = NSURLSessionAuthChallengePerformDefaultHandling,确定处理方式这个参数的值。如果options是SDWebImageDownloaderAllowInvalidSSLCertificates呢,也就是允许无效的整数,那么按照下面进行处理。

credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
disposition = NSURLSessionAuthChallengeUseCredential;

实例化新的NSURLCredential证书,并且设置dispose为使用指定的证书这个枚举值NSURLSessionAuthChallengeUseCredential,在这一点上都是类似的,AFN有一部分也是这么做的。

3. else条件判断

如果服务器返回的证书不是服务器信任的。那么,按照下面这小段逻辑进行处理。

else {
        if (challenge.previousFailureCount == 0) {
            if (self.credential) {
                credential = self.credential;
                disposition = NSURLSessionAuthChallengeUseCredential;
            } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    }

这里首先判断以前的质询次数,对应previousFailureCount这个属性。

/*!
    @abstract Get count of previous failed authentication attempts
    @result The count of previous failures
*/
@property (readonly) NSInteger previousFailureCount;

如果质询失败次数为0,接着进行判断,如果有证书,那么disposition = NSURLSessionAuthChallengeUseCredential;,如果没有证书,那么disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;,也就是整个的请求将被取消,忽略credential参数。

如果质询失败次数不为0,那么disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;,作用同上。


completionHandler回调

上面的参数构建完毕后,紧接着就是completionHandler这个block的回调。回调就是这两个参数,处理方式和证书completionHandler(disposition, credential);

参考文章

1. iOS - HTTPS
2. 打造安全的App!iOS安全系列之 HTTPS

后记

本篇主要解析的就是质询时候的代理处理方法,构造disposition和credential两个参数,并且回调作为输入参数传过去。

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

推荐阅读更多精彩内容