前端Cookie处理

在浏览器端,虽然以LocalStorage为表明的本地持久化方案已经很是成熟,但cookie因其可跨三级及以上域名、可后端参与操做等特性,在涉及用户验证等诸多业务中依然被普遍运用。html

Cookie规格

Cookie的基本组成主要由4部分组成:前端

  • Key => Value 存储数据
  • Path 做用路径
  • Domain 做用域
  • Expires 过时时间,或者叫生命周期

咱们能够用谷歌控制台体会一下。web

打开suning.com,而后在控制台输入如下代码:小程序

document.cookie = `my_data=123; expires=${new Date(2021,0,1).toGMTString()};`
复制代码

而后进入Application->Cookie->https://www.suning.com,能够看到my_data已经被写入列表。后端

在上面的例子中,咱们并无指定PathDomain两个值,因此浏览器给出了默认值:跨域

  • Path=/ 做用于根及如下分支目录
  • Domain=www.suning.com 做用于该域

若是但愿Cookie在三级及以上域名做用,可简单加一条:浏览器

document.cookie = `my_data=123; domain=suning.com; expires=${new Date(2021,0,1).toGMTString()};`
复制代码

能够看到,Cookie中增长了一条my_data记录domain=.suning.com。这里的.suning.com能够理解*.suning.com安全

关于Path项及其余Cookie项,这里就很少作解释了,你们能够自行尝试或者查询资料,在控制台里尽情虐待浏览器的cookie。bash

这里有几个小的经验追加一下:服务器

  1. 日期格式很是松散。GMT时间格式是Cookie的标准时间格式,但其余时间格式谷歌浏览器也能够识别,这个方面你们能够本身探索一下,就不赘述了。由于单纯是日期格式问题,就能够写好多字。
  2. Expires时间是UTC时间。
  3. 浏览器的document.cookie虽然是以字符串形式赋值与取值,但其背后的管理机制倒是相似Map类型。
  4. Cookie的销毁,是经过设置expires为一个过去时,但须要注意其domain path等须要对应。好比:
document.cookie = `my_data=123; domain=suning.com; expires=${new Date(0).toGMTString()};`
复制代码

后端Set-Cookie

后端往前端塞cookie是一种经常使用操做,方法是在响应头中设置set-cookie。浏览器会接收这个头部,并原样设置到本地cookie中。

Set-Cookie: <name>=<value>[; <name>=<value>]...
   [; expires=<date>]
   [; domain=<domain_name>]
   [; path=<some_path>]
   [; secure]
   [; httponly]
复制代码

这个格式看起来是否是与刚才设置document.cookie一致?补充最后两项说明:

  • secure表示cookie只能被发送到http服务器。
  • httponly表示cookie不能被客户端脚本获取到。

关于HTTP响应头,这里提两个注意事项:

  1. 头部的KEY能够重复多个。也就是说,头部是有可能出现多个set-cookie的。以前我曾遇到这样一个案例:后端工程师使用NodeJS+KOA作服务,对容许跨域的请求设置了头部Access-Control-Allow-Origin: *。当服务使用Docker部署后,运维的同窗对前置的Nginx也配置了Access-Control-Allow-Origin,因此前端拿到的响应头中出现两个Access-Control-Allow-Origin。结果浏览器断定此项头配置无效,形成跨域请求失败。固然,set-cookie出现多个没有问题,只是此种状况须要作适配处理。
  2. 头部的KEY大小写不敏感。但这不表明处理头部的应用会大小写不敏感。

Cookie与encodeURI

关于URI/URL/URN

  • URI: Uniform Resource Identifier
  • URL: Uniform Resource Locator
  • URN: Uniform Resource Name

在进行web访问时,一个web地址(URL)由protocol+domain+path组成。

  • protocol: http/https/ftp 等等
  • domain: 相似www.suning.com
  • path: /aaa/b/cc/d.html 酱婶儿的 这样就造成了对一个网络资源的有效定位,也就是一个Locator。而这个URL实际上在全网范围也是一个惟一标识,因此也是一个URI。简单点说,URL是URI的一种。

URN我没有遇到(意识到?)典型的场景,按RFC来说一样是URI的一个子集。

关于encodeURI与encodeURIComponent

这二者的区别在于对URI转义的字符集不一样。encodeURI并不会对一个URI的分割标记作出转移,好比://#()?&=...,等等。

encodeURIComponent望文生义的话,是对URI部分的转义,意图是被转义的部分不影响URL的解析,那么就必须将其中的URI定义的字符所有转义。例子:

window.location.href = `https://auth.suning.com?redir=${encodeURIComponent('https://www.suning.com')}`;
// https://auth.suning.com?redir=https%3A%2F%2Fwww.suning.com
window.location.href = `${encodeURI('https://www.suning.com/prod.do?location=北京')}`;
// https://www.suning.com/prod.do?location=%E5%8C%97%E4%BA%AC
复制代码

最终的目的,是在不破坏URI的前提下,完整传递参数。

encodeURI在Cookie操做中的应用

咱们获取cookie的途径,不只是响应头的set-cookie。也许是localStorage数据,也许是一次API请求。

因为HTTP规范中,头中只容许使用ASCII字符,因此在向请求头塞cookie的时候,须要对cookie来源的字符串作预处理。这时候,就用到了encodeURI/encodeURIComponent。因为在GMT时间格式中存在URI的敏感字,也就是说,被encodeURI的忽略的字符集,小于header容许的字符集。因此一次性encode并不可取,需在cookie拼接完成后,作全量分析和处理。

Cookie字符串的切割与分析

如文章开头所说,为了兼容、复用一些老的登陆框架,每每须要用到cookie处理机制。因为前端AJAX没法处理302请求问题,也就没法处理写cookie跳转的登陆行为,因此你可能须要一个后端接口去代理一系列的后端set-cookie行为。

假设中间咱们跳转了两个页面,每一个页面set-cookie一次,那么在代理页面返回的响应头中,会至少包含2条set-cookie头部。出于安全考虑,XMLHttpRequest并不能拿到头部的set-cookie,因此接下来,咱们用小程序中的request方法,来做为进一步演示cookie处理问题的工具。

(依然未完)

相关文章
相关标签/搜索