版本记录
版本号 | 时间 |
---|---|
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 disposition
和NSURLCredential *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两个参数,并且回调作为输入参数传过去。