cookie原理&WK如何设置Cookie

一、cookie简单介绍

Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会自动的被浏览器存储然后在下一次请求该服务器网络资源时又返还给该服务器,Cookie 又称之 web Cookie 或 browser cookie

cookie 的使用场景:

Session管理: 如 登录、购物车、积分、或者如何有浏览器操作记录并同时应记录在服务端的数据。
个性设置 如:用户偏好、web主题、其他个性设置
跟踪 如:记录和分析用户习惯

最常见的就是使用cookie作状态验证,由于Http通信是无状态的,在登录页面设计的时候,往往会利用cookie 作为浏览器状态信息来确认当前用户是否处于登陆状态。

当一个浏览器向一个服务器发送请求的时候该服务器就会在response的时候自动发送Set-Cookie header给浏览器,一般如下:

Set-Cookie: key=value
Set-Cookie: key=value;  Expires=<date>
Set-Cookie: key=value;  Max-Age=<non-zero-digit>
Set-Cookie: key=value;  Secure
Set-Cookie: key=value;; HttpOnly

浏览器端 Cookie类型分为 session cookie 和 permanent cookie,他们之间的区别在于前者只要在浏览器关闭后 cookie就会消失,而permanent cookie则不会,二者设置的区别在于cookie设置的时候是否添加了expires 或者 max-age 属性。

另外还有一点值得注意的是cokie的安全问题,因为浏览器端用户可以直接调用document.cookie 取 cookie,所以在这里恶意代码也可以轻易通过 documen.cookie 获取到当前用户cookie中的敏感信息,如 UserId、token等。所以在应用设计时有些 cookie要设置为 httpOnly cookie。这样cookie就只能被服务端读取,而浏览器获取不到任何cookie 信息。所以如果是token这类的敏感信息,绝不能存储在http cookie中,因为很容易受到劫持。原则上,cookie设置https 读取是起码的规定,如果可以的话,最好放置在httpOnly cookie中。

Cookie 的几个字端详解

域 Domain
指定了哪些主机可以接受 cookie,如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了Domain,则一般包含子域名(子域名可以访问父域名的cookie)

例如:如果设置 Domain = hhh.org,则 cookie也包含在子域名中(如:develop.hhh.org)

Path
Path 标示指定了主机下的哪些路径可以接受cookie (该URL路径必须存在于请求URL中)。以字符 %x2F (/)作为路径分隔符,子路径也会被匹配。

设置 Path = /docs ,则以下地址都会匹配
/docs
/docs/web
/docs/web/http 

Expires / Max-Age
Cookie 的过期时间,过了这个时间之后cookie 将会自动删除。

Set-Cookie: id=a3fWa;   Expires=Fri,    21  Oct 2019    07:28:00    GMT;

Max-Age 的单位是秒

document.cookie =   'promo_shown=1; Max-Age=2600000;    Secure'

HttpOnly

为了避免跨域脚本(XSS)攻击,通过JavaScript 的docment.cookie API 无法访问带有HttpOnly 标记的cookie,它们只应该发送给服务器。如果包含服务端session信息的 Cookie 不想被客户端javaScript 脚本调用,那么就应该为其设置 HttpOnly 标记。

Set-Cookie: id=a3fOa;   Expires=Fri,    21  Oct 2019    07:28:00    GMT;    Secure; HttpOnly

Secure

标记为secure 的cookie 只应通过被Https 协议加密过的请求发送给服务端。

SameSite

SameSite Cookie 允许服务器要求某个cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击。

Set-Cookie: key=value;  SameSite=Strict

其可选取值:
None : 浏览器会在同站请求、跨站请求下继续发送Cookies,不区分大小写;
Strict :浏览器将只发送相同站点请求的cookie (即当前网页URL与请求目标URL完全一致)。如果请求来自与当前location的URL 不同的URL,则不包括标记为Strict属性的Cookie;
Lax :在新版浏览器中,为默认选项,Same-site Cookie 将会为一些跨站请求保留。

二、WKWebView 中的 cookie问题

由于WK整个框架的改变,WK已经不单单是在App 这一侧,WK容器发起的H5请求已经不在App进程中发起和响应处理,而是在专门的web进程中处理,所以WK的网络请求无法直接从NSHTTPCookieStorage取到cookie,从而导致当H5访问一些带鉴权的接口就会出现问题。

而原来UIWebView 作为H5的容器,后台下发的cookie会自动存储到NSHTTPCookieStrorage这个容器中,webView 内部的请求会自动从NSHTTPCookieStorage获取合适的cookie带上去。而WK内有一个自己独立的cookie的容器,因为这个容器与App侧的NSHttpCookieStorage里的cookie的同步是进程级别的同步,并且是单向的,这就导致WK第一次请求无法及时没有带上App侧的cookie。

腾讯一个权威团队在解决WK的cookie 建议我们采用这种思路:通过key-Value构造一个cookie,WK loadRequest前,在request header 中设置 cookie ,解决首个请求cookie 带不上的问题,通过 docment.cookie 设置Cookie解决后续页面(同域)Ajax、ifFrame请求的,下面我们这里也是建议大家采用这种思路来解决cookie的问题。

首先我们在WK在发第一个request请求时,向request里设置好cookie,确保我们的请求在服务器端那边收到时是可以签权通过的,看下面代码:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//request携带
[request      setHTTPShouldHandleCookies:YES];
//cookie直接设置name,value
[request    setValue:[NSString  stringWithFormat:@"%@=%@;",@"name", @"lisi"]    forHTTPHeaderFie
ld:@"Cookie"];

注意: 这里我们是直接设置cookie的name,value,这样设置cookie显然是不够的,这样做你可能创建出多个相同名字的cookie ,另外如果只是简单构造key-value,可能还会导致因为同源策略的请求带不上cookie。正确的方式应该是要求我们构造出一个完整的cookie串,看下面代码:

//构造完整的cookie串
NSHTTPCookie *cookie = [DCookieViewController cookieWithDomain:url.host   name:@"name"  value:@"lisi2"];

 [request setValue:[NSString stringWithFormat:@"%@;",[self_getCookieString:cookie]]  forHTTPHeaderField:@"Cookie"]; 

- (NSString *)_getCookieString:(NSHTTPCookie *)cookie   
{
NSString  *string   = [NSString stringWithFormat:@"%@=%@;domain=%@;expiresDate=%@;path=%@;sessionOnly=%@;isSecure=%@",cookie.name,cookie.value,cookie.domain,cookie.expiresDate,cookie.path ?: @"/",cookie.isSecure ? @"TRUE":@"FALSE",cookie.sessionOnly ? @"TRUE":@"FALSE"];

return  string;
 }

除了我们要在request 里设置好cookie ,保证App的WK 这边发出去的请求,在服务端那边是认可以外,我们还需要保证客户端的H5那边也能拿到我们App里的Cookie,那我们就需要另外再做一件事了,就是用JS脚本注入的方式去设置,保证H5那边也能拿到我们App原生的cookie。

注入JS脚本设置cookie

//通过document.cookie设置Cookie
WKUserContentController*  userContentController = [[WKUserContentController  alloc]  init];
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource: @"document.cookie = 'name=lisi_handsome';" injectionTime:WKUserScriptInjectionTimeAtDocumentStart  forMainFrame
Only:NO]; 
[userContentController  addUserScript:cookieScript];
configuration.userContentController =   userContentController;

另外如果我们要把NSHTTPCookieStorage 的cookie也带过去,可以采用以下方法:

//js方式设置cookie
- (NSString *)setCcookieJS  
{
NSMutableString *jsScript = [NSMutableString    string]; [jsScript  appendString:@"var  cookieNames = document.cookie.split(';  ').map(function(cookie) { return cookie.split('=')[0] } );\n"];
for (NSHTTPCookie   *cookie in [[NSHTTPCookieStorage    sharedHTTPCookieStorage] cookies]) {
if ([cookie.value   rangeOfString:@"'"].location    !=  NSNotFound) 
{
continue; 
}
NSString *string    = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",cookie.name,cookie.value,   cookie.domain,cookie.path ?: @"/"];
 [jsScript appendFormat:@"if    (cookieNames.indexOf('%@')  ==  -1) 
{   
document.cookie='%@'; };\n", cookie.name, string]; 
}
return  jsScript; 
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,373评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,732评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,163评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,700评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,036评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,425评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,737评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,421评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,141评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,398评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,908评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,276评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,907评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,018评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,772评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,448评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,325评论 2 261

推荐阅读更多精彩内容