WKWebView Cookie 設(shè)置

從UIWebview換到WKWebView之后,會(huì)發(fā)現(xiàn)管理Cookie是很麻煩事眠菇,經(jīng)常出現(xiàn) App自定義Cookie的值丟失 或 更新不及時(shí) 的情況边败。蘋果iOS11之后也提供了WKWebView的Cookie API WKHTTPCookieStore,但是目前大多數(shù)App最低版本不可能設(shè)置最低版本到iOS11捎废,所以我們只能想別的辦法笑窜。

什么是Cookie?

Cookie是一種早期的客戶端存儲(chǔ)機(jī)制,起初是針對(duì)服務(wù)端腳本設(shè)計(jì)使用的登疗。以Cookie存儲(chǔ)的數(shù)據(jù)排截,不論服務(wù)端是否需要,每次HTTP請(qǐng)求都會(huì)把這些數(shù)據(jù)傳送到服務(wù)端辐益。

Cookie是指Web瀏覽器存儲(chǔ)的少量數(shù)據(jù)断傲,同時(shí)它是與具體的Web頁(yè)面或者站點(diǎn)相關(guān)。Cookie最早是設(shè)置為被服務(wù)端所用的智政,從最底層來(lái)看认罩,作為http協(xié)議的一種拓展實(shí)現(xiàn)它。

Cookie數(shù)據(jù)會(huì)自動(dòng)在Web瀏覽器和Web服務(wù)器之間傳輸续捂,因此服務(wù)端腳本就可以讀寫存儲(chǔ)在客戶端的cookie值垦垂。

Cookie的屬性

除了 name 與 value闺金,Cookie其他屬性:

domain:作用域名

舉例:
設(shè)置domain為 bj.jiehun.com.cn,則在app.jiehun.com.cn 等子域名不會(huì)生效攻谁;
如設(shè)置domain為 .jiehun.com.cn笤喳,則在jiehun.com.cn 的所有子域名生效勺疼。
注意:IP地址特殊,直接設(shè)置原地址即可页慷。

path:作用路徑

舉例:
如在 www.jiehun.com.cn撇簿,設(shè)置 path=/m,則只在 www.jiehun.com.cn/m 或 /m子目錄下生效差购,如 www.jiehun.com.cn/app 就不會(huì)生效;
不設(shè)置默認(rèn)為當(dāng)前URL默認(rèn)路徑汉嗽;我們通常會(huì)設(shè)置 “/” 代表所有目錄欲逃。

expires:過(guò)期時(shí)間,格林威治時(shí)間 (GMT)字符串格式饼暑,設(shè)置過(guò)期時(shí)間后將會(huì)存儲(chǔ)在一個(gè)文件直到過(guò)期稳析。

// 打印當(dāng)前時(shí)間
var date = new Date();
date.setTime(date.getTime());
console.log(date.toGMTString());
// 打印結(jié)果為:Mon, 25 Feb 2019 15:35:03 GMT

// 設(shè)置cookie時(shí)間
document.cookie='name=value;expires=' + date.toGMTString();

max-age:有效時(shí)長(zhǎng)弓叛,單位秒彰居。

// 設(shè)置 cookie 有效期 10秒
document.cookie='name=value;max-age=10;

Cookie默認(rèn)的有效期很短暫,只能維持在Web瀏覽器的回話期間撰筷,一旦用戶關(guān)閉瀏覽器陈惰,Cookie保存的數(shù)據(jù)就全部丟失。
如果想要延長(zhǎng)Cookie的有效期毕籽,可以通過(guò)設(shè)置max-age或expires屬性抬闯。一旦設(shè)置有效期,瀏覽器就會(huì)將Cookie數(shù)據(jù)存儲(chǔ)在一個(gè)文件中关筒,并且直到過(guò)了指定的有效期才會(huì)刪除該文件溶握。

secure: Bool值,是否為安全傳輸蒸播,如設(shè)置true睡榆,在Https或其他網(wǎng)絡(luò)安全協(xié)議才會(huì)傳輸。

演示

我們可以隨便找一個(gè)瀏覽器袍榆,如Safari胀屿,打開后快捷鍵 command + alt + c 打開調(diào)試窗口:


image.png

讀取Cookie

document.cookie

保存Cookie

document.cookie='testName=testValue;path=/;max-age=60*60';

因?yàn)镃ookie的名和值中不允許包含分號(hào)、逗號(hào)和空格蜡塌,因此碉纳,在存儲(chǔ)前可以采用全局函數(shù) encodeURIComponent()對(duì)值進(jìn)行編碼。相應(yīng)的馏艾,讀取cookie值的時(shí)候采用decodeURIComponent() 函數(shù)解碼劳曹。

刪除Cookie

相同的名字隨意設(shè)置一個(gè)值奴愉,并將max-age指定為0,相當(dāng)于刪除Cookie铁孵。

document.cookie='testName=;domain=.jiehun.com.cn;path=/;max-age=0';

Cookie的局限性

個(gè)數(shù)限制300(現(xiàn)在已經(jīng)可以超越)锭硼,每個(gè)Cookie數(shù)據(jù)即名字和值的總量不能超過(guò)4KB。

WKWebView 管理Cookie

上面了解了Cookie的基本知識(shí)蜕劝,我們?nèi)绾螒?yīng)用到iOS開發(fā)中檀头?這里主要介紹WKWebview的使用方法。

因?yàn)镴avaScript只能設(shè)置瀏覽器本地的cookie岖沛,往往客戶端第一次請(qǐng)求由開發(fā)者創(chuàng)建Request對(duì)象請(qǐng)求:

[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"url"]]];

所以第一次請(qǐng)求需要手動(dòng)設(shè)置請(qǐng)求頭中的Cookie,可以繼承WKWebView重寫 loadRequest 方法暑始,或者直接通過(guò)runtime Swizzling loadRequest 方法:

/**重寫 loadRequest 方法,在請(qǐng)求頭中添加自定義到cookie*/
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request{
    
    NSMutableURLRequest *newRequeset = [request mutableCopy];
    
    // 自定義cookie值
    NSDictionary *customCookieDic =@{
                                     @"testName1":@"value1",
                                     @"testName2":@"value2"
                                     };
    
    // 拼接cookie字符
    NSString *cookie = @"";
    for (NSString *key in customCookieDic.allKeys) {
        NSString *keyValue = [NSString stringWithFormat:@"%@=%@;",key,[customCookieDic objectForKey:key]];
        cookie = [cookie stringByAppendingString:keyValue];
    }
    
    // 設(shè)置到請(qǐng)求頭
    [newRequeset setValue:cookie forHTTPHeaderField:@"Cookie"];
    
    return [super loadRequest:newRequeset];
}

此時(shí)請(qǐng)求發(fā)出婴削,服務(wù)端可以收到我們請(qǐng)求頭中的cookie值廊镜,且請(qǐng)求頭的cookie會(huì)自動(dòng)保存到瀏覽器。

但我們發(fā)現(xiàn)請(qǐng)求頭中自動(dòng)保存到瀏覽器的cookie并不可靠唉俗,因?yàn)闆](méi)有設(shè)置域名和目錄的作用區(qū)嗤朴,往往瀏覽器內(nèi)二次跳轉(zhuǎn)就會(huì)丟失,我們?nèi)绾蝸?lái)保證瀏覽器的Cookie永不丟失虫溜?

WKUserScript

Webkit支持通過(guò) WKUserScript 向網(wǎng)頁(yè)中注入js腳本:

// 設(shè)置代碼塊
// @Source 腳本代碼
// @injectionTime 執(zhí)行時(shí)機(jī)雹姊,網(wǎng)頁(yè)渲染前或渲染后
// @MainFrameOnly Bool值,YES只注入主幀衡楞,NO所有幀
WKUserScript *cookieInScript = [[WKUserScript alloc] initWithSource:@"js腳本代碼"
                                                              injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                           forMainFrameOnly:NO];
// 插入腳本
[webview.configuration.userContentController addUserScript:cookieInScript];

所以吱雏,保證Cookie不丟失可以通過(guò)此方法注入設(shè)置cookie js代碼,在頁(yè)面每次渲染都會(huì)設(shè)置瘾境,從而保證不會(huì)丟失坎背。

每個(gè)cookie值可以設(shè)置為一個(gè)代碼塊,為了表示每個(gè)代碼塊的唯一寄雀,我們可以在注入腳本的最后添加 注釋標(biāo)示得滤;其實(shí)就是一句注釋掉的代碼,來(lái)確定cookie代碼塊的唯一性盒犹,為以后刪除某個(gè)代碼塊做鋪墊懂更。
舉例設(shè)置某個(gè)cookie值的 js代碼:

document.cookie ='cityId=10010;domain=.jiehun.com.cn;path=/';
// The cookie code  identified is cityId (代碼塊標(biāo)示)

為了避免Cookie重復(fù)問(wèn)題,可以直接把cookie設(shè)置在根域名急膀。

刪除代碼塊

每次調(diào)用 addUserScript方法插入腳本塊沮协,代碼塊會(huì)保存在WKUserContentController類的 userScripts數(shù)組屬性中:

@interface WKUserContentController : NSObject <NSSecureCoding>

/*! @abstract The user scripts associated with this user content
 controller.
*/
@property (nonatomic, readonly, copy) NSArray<WKUserScript *> *userScripts;

因?yàn)?userScripts 為只讀權(quán)限,我們并不能修改卓嫂,所以修改某個(gè)某一個(gè)cookie代碼塊的時(shí)候慷暂,需要先全部清除,再把不需要?jiǎng)h除的代碼塊重新添加進(jìn)去晨雳,這里就需要用到前面所說(shuō)的代碼塊注釋的唯一標(biāo)示:

/**
 刪除某個(gè)代碼片段
 @param tag 片段標(biāo)示行瑞,//The cookie code  identified is cookieName
 */
- (void)deleteUserSciptWithTag:(NSString *)tag {
    
    if (tag) {
        WKUserContentController *userContentController = webView.configuration.userContentController;
        NSMutableArray<WKUserScript *> *array = [userContentController.userScripts mutableCopy];
        int i = 0;
        BOOL isHave = NO;
        for (WKUserScript* wkUScript in userContentController.userScripts) {
            // 通過(guò)注釋標(biāo)示判斷代碼塊是否為某個(gè)cookie
            if ([wkUScript.source containsString:tag]) {
                [array removeObjectAtIndex:i];
                isHave = YES;
                continue;
            }
            i ++;
        }
        
        if (isHave) {
            ///沒(méi)法修改數(shù)組 只能移除全部 再將不需要?jiǎng)h除的cookie重新添加
            [userContentController removeAllUserScripts];
            for (WKUserScript* wkUScript in array) {
                [userContentController addUserScript:wkUScript];
            }
        }
    }
}

通過(guò)這個(gè)Webkit可注入腳本的邏輯奸腺,我們基本可以保證使用cookie在WKWebview準(zhǔn)確性和不丟失。

下面也寫了一個(gè)Demo來(lái)演示如何通過(guò)一個(gè)代理方法來(lái)管理WKWebView所有Cookie:
github地址:https://github.com/GaoGuohao/GGWkCookie

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末血久,一起剝皮案震驚了整個(gè)濱河市突照,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氧吐,老刑警劉巖讹蘑,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異筑舅,居然都是意外死亡座慰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門翠拣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)角骤,“玉大人,你說(shuō)我怎么就攤上這事心剥。” “怎么了背桐?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵优烧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我链峭,道長(zhǎng)畦娄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任弊仪,我火速辦了婚禮熙卡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘励饵。我一直安慰自己驳癌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布役听。 她就那樣靜靜地躺著颓鲜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪典予。 梳的紋絲不亂的頭發(fā)上甜滨,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音瘤袖,去河邊找鬼衣摩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捂敌,可吹牛的內(nèi)容都是我干的艾扮。 我是一名探鬼主播既琴,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼栏渺!你這毒婦竟也來(lái)了呛梆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磕诊,失蹤者是張志新(化名)和其女友劉穎填物,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霎终,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滞磺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了莱褒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片击困。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖广凸,靈堂內(nèi)的尸體忽然破棺而出阅茶,到底是詐尸還是另有隱情,我是刑警寧澤谅海,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布脸哀,位于F島的核電站,受9級(jí)特大地震影響扭吁,放射性物質(zhì)發(fā)生泄漏撞蜂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一侥袜、第九天 我趴在偏房一處隱蔽的房頂上張望蝌诡。 院中可真熱鬧,春花似錦枫吧、人聲如沸浦旱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闽寡。三九已至,卻和暖如春尼酿,著一層夾襖步出監(jiān)牢的瞬間爷狈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工裳擎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涎永,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像羡微,于是被迫代替她去往敵國(guó)和親谷饿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容