Web服务可以在返回HTTP响应时附带认证要求(authentication challenge),其作用是询问“HTTP请求的发起方是谁?”这时发起方应该提供相应的用户名和密码(即认证信息),只有当认证通过后,Web服务才会返回真正的HTTP响应。
当应用收到认证要求时,NSURLSession的委托会收到URLSession:task: didReceiveChallenge:completionHandler:消息,可以在该消息中发送用户名和密码,完成认证。
打开BNRCoursesViewController.m,更新fetchFeed方法,访问安全度更高的Big Nerd Ranch在线课程Web服务(注意将http改为https),代码如下:
- (void)fetchFeed
{
NSString *requestString =
@“http://bookapi.bignerdranch.com/courses.json”;
NSString *requestString =
@“https://bookapi.bignerdranch.com/private/courses.json”;
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
下面需要在初始化BNRCoursesViewController时为NSURLSession设置委托。更新initWithStyle:方法,代码如下:
- (instancetype)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
self.navigationItem.title = @“BNR Courses”;
NSURLSessionConfiguration *config =
[NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
_session = [NSURLSession sessionWithConfiguration:config
delegate:self
delegateQueue:nil];
[self fetchFeed];
}
return self;
}
然后在BNRCoursesViewController.m的类扩展中,使BNRCoursesViewController遵守NSURLSessionDataDelegate协议:
@interface BNRCoursesViewController ()<NSURLSessionDataDelegate>
@property (nonatomic) NSURLSession *session;
@property (nonatomic, copy) NSArray *courses;
@end
构建并运行应用,Web服务会返回一条错误消息:未认证的访问请求(unauthorized access)。因此,Web服务不会返回任何数据,UITableView对象中也没有显示任何在线课程信息。
为了通过Web服务认证,需要实现NSURLSession收到认证要求的委托方法。该方法会提供一个Block对象,可以将认证信息传入这个Block对象,完成认证。
在BNRCoursesViewController.m中,实现URLSession:task:didReceiveChallenge: completionHandler:方法,处理Web服务的认证要求:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:
(void (^)(NSURLSessionAuthChallengeDisposition,
NSURLCredential *))completionHandler
{
NSURLCredential *cred = [NSURLCredential
credentialWithUser:@“BigNerdRanch”
password:@“AchieveNerdvana”
persistence:NSURLCredentialPersistenceForSession];
completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
}
completionHandler有两个参数。第一个参数是认证类型,由于NSURLCredential对象中提供了用户名和密码,因此类型是NSURLSessionAuthChallengeUseCredential。第二个参数是认证信息,即NSURLCredential对象。以上代码使用NSURLCredential的工厂方法credentialWithUser:password:persistence:创建NSURLCredential对象,该方法需要提供用户名、密码和认证信息的有效期限(有效期限是一个枚举值)。
构建并运行应用,运行结果与之前的相同。但是现在应用访问的是安全度更高的Big Nerd Ranch在线课程Web服务。