[- URLSession:didBecomeInvalidWithError:]
如果你使用finishTasksAndInvalidate函数使该session失效,那么session首先会先完成最后一个task,
然后再调用URLSession:didBecomeInvalidWithError:代理方法,
如果你调用invalidateAndCancel方法来使session失效,那么该session会立即调用上面的代理方法。
[- URLSession:didReceiveChallenge:completionHandler:]
web服务器接收到客户端请求时,有时候需要先验证客户端是否为正常用户,再决定是够返回真实数据。
这种情况称之为服务端要求客户端接收挑战(NSURLAuthenticationChallenge *challenge)。
接收到挑战后,客户端要根据服务端传来的challenge来生成completionHandler所需的NSURLSessionAuthChallengeDisposition disposition和NSURLCredential *credential
(disposition指定应对这个挑战的方法,而credential是客户端生成的挑战证书,注意只有challenge中认证方法为NSURLAuthenticationMethodServerTrust的时候,才需要生成挑战证书)。
最后调用completionHandler回应服务器端的挑战。
如果你没有实现该方法,该session会调用其NSURLSessionTaskDelegate的代理方法
URLSession:task:didReceiveChallenge:completionHandler:
- (void) URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
//挑战处理类型为 默认
/*
NSURLSessionAuthChallengePerformDefaultHandling:默认方式处理
NSURLSessionAuthChallengeUseCredential:使用指定的证书
NSURLSessionAuthChallengeCancelAuthenticationChallenge:取消挑战
*/
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
// sessionDidReceiveAuthenticationChallenge是自定义方法,用来如何应对服务器端的认证挑战
if (self.sessionDidReceiveAuthenticationChallenge) {
disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential);
} else {
// 此处服务器要求客户端的接收认证挑战方法是NSURLAuthenticationMethodServerTrust
// 也就是说服务器端需要客户端返回一个根据认证挑战的保护空间提供的信任(即challenge.protectionSpace.serverTrust)产生的挑战证书。
// 而这个证书就需要使用credentialForTrust:来创建一个NSURLCredential对象
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
// 基于客户端的安全策略来决定是否信任该服务器,不信任的话,也就没必要响应挑战
if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
// 创建挑战证书(注:挑战方式为UseCredential和PerformDefaultHandling都需要新建挑战证书)
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
// 确定挑战的方式
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
// 取消挑战
disposition = NSURLSessionAuthChallengeRejectProtectionSpace;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
// 必须调用此方法,完成认证挑战
if (completionHandler) {
completionHandler(disposition, credential);
}
}
响应认证
可以在
URLSession:didReceiveChallenge:completionHandler:
或
URLSession:task:didReceiveChallenge:completionHandler:
代理方法中响应认证。
提供凭据
认证需要创建一个服务器期望的NSURLCredential对象,该对象可以通过 authenticationMethod 来制定认证方式。下面是几种认证方式:
- HTTP基本认证(NSURLAuthenticationMethodHTTPBasic)需要用户名和密码。通过如下创建NSURLCredential对象;
credentialWithUser: password:persistence:
- HTTP摘要认证(NSURLAuthenticationMethodHTTPDigest),类似于基本认证,不过在提供用户名和秘密后,摘要会自动生成。
通过如下创建NSURLCredential对象;
credentialWithUser: password:persistence:.
- 客户端证书认证(NSURLAuthenticationMethodClientCertificate)需要系统识别出所有服务器需要的证书。
通过如下创建NSURLCredential对象;
credentialWithIdentity:certificates:persistence:
- 服务器信任认证(NSURLAuthenticationMethodServerTrust)需要一个信任对象,
通过创建NSURLCredential对象。
credentialForTrust:
在创建完NSURLCredential对象后,将该对象传递给对应的完成处理句柄。
继续无凭据
如果代理方法不能提供有效凭据,可以尝试继续无凭据访问。可将下面两个值之一传给完成句柄:
NSURLSessionAuthChallengePerformDefaultHandling 处理请求就像代理没有提供处理认证的代理方法一样。
NSURLSessionAuthChallengeRejectProtectionSpace 拒绝认证。根据服务器的响应,URL loading class可能会在多个受保护的空间进行多次调用该代理方法。
取消认证
将值NSURLSessionAuthChallengeCancelAuthenticationChallenge 传递给完成句柄即可。
网友评论