項目需求
公司后端API調(diào)用李剖,經(jīng)歷多次302重定向弊琴,初始請求需在請求頭中攜帶Referer,調(diào)用成功后杖爽,可進(jìn)行數(shù)據(jù)下載敲董。
實際問題
使用NSURLSession進(jìn)行網(wǎng)絡(luò)下載請求,跳轉(zhuǎn)兩次后cookie丟失及請求頭中Referer消失慰安,導(dǎo)致請求失敗返回認(rèn)證失敗網(wǎng)頁腋寨。
解決思路
攔截跳轉(zhuǎn)請求,獲取下次跳轉(zhuǎn)的URL化焕,強制添加消失的cookie及請求頭的Referer萄窜,再進(jìn)行跳轉(zhuǎn)。
實現(xiàn)方法
- 項目文檔中注冊代理類(我的項目為DownloadManager撒桨,請自行替換)
@interface DownloadManager()<NSCopying, NSURLSessionDelegate>
- 繼承代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
//此函數(shù)為不進(jìn)行任何操作直接用返回的request進(jìn)行下一步跳轉(zhuǎn)查刻,
//若使用completionHandler(nil),則不會進(jìn)行跳轉(zhuǎn)
completionHandler(request);
//返回的task具有唯一性凤类,可用來識別是哪個發(fā)送的請求:task.taskIdentifier
//返回的response中可以獲取到服務(wù)器返回的Set-Cookie
//返回的request中可以獲取到即將跳轉(zhuǎn)的鏈接地址
}
- 實際代碼
以下為項目需要進(jìn)行的操作穗泵,實際可以根據(jù)自己需求進(jìn)行更改,定義了一個SessionModel來存儲對應(yīng)的task.taskIdentifier及相應(yīng)的Referer等信息谜疤,我實際遇到的問題為跳轉(zhuǎn)請求的cookie中LID的value丟失佃延,所以代碼內(nèi)進(jìn)行了LID的賦值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
NSLog(@"cookie%@", cookie);
//手動設(shè)置LID (實際需求可以和后端開發(fā)協(xié)商
if([cookie.name isEqualToString:@"LID"]) {
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; // 創(chuàng)建cookie屬性字典
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName]; // 手動設(shè)置cookie的name
[cookieProperties setObject:@"LID" forKey:NSHTTPCookieValue];//手動設(shè)置cookie的value
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"HOST" forKey:NSHTTPCookieDomain];//設(shè)置cookie的host地址
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];//保存cookie
}
}
//用返回的request.URL初始化請求,因為公司下載服務(wù)不穩(wěn)定夷磕,故設(shè)置超時時間為100s
//NSURLRequestReloadRevalidatingCacheData:驗證本地數(shù)據(jù)與遠(yuǎn)程數(shù)據(jù)是否相同履肃,如果不同則下載遠(yuǎn)程數(shù)據(jù),否則使用本地數(shù)據(jù)
NSMutableURLRequest *nextRequest = [NSMutableURLRequest requestWithURL:request.URL
cachePolicy:NSURLRequestReloadRevalidatingCacheData
timeoutInterval:100];
//getSessionModel:為自定義方法,并設(shè)置Referer
SessionModel *sessionModel = [self getSessionModel:task.taskIdentifier];
[nextRequest setValue:sessionModel.refer forHTTPHeaderField:@"Referer"];
//發(fā)送下個請求
completionHandler(nextRequest);
}