yaofly2012 / note

Personal blog
https://github.com/yaofly2012/note/issues
44 stars 5 forks source link

Http-cookie #117

Open yaofly2012 opened 4 years ago

yaofly2012 commented 4 years ago

再看cookie

  1. npm cookie库,
  2. nodejs/express/客户端 如何操作cookie,
  3. cookie间隔为啥是'; '
  4. https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/parseCookie.md
  5. cookie跨域问题
  6. 历史:引入背景,和localstorage, sessionstorage差异
  7. cookie的安全
yaofly2012 commented 4 years ago

一、概述

1.1 什么是Cookie

Cookie是服务器存储在客户端的数据(小段文本)。 这是见过最好的描述,你品,你细品。

1.2 为啥需要Cookie

HTTP是stateless,Cookie是实现HTTP State Management Mechanism。

  1. HTTP客户端通过Cookie让HTTP Server识别自己;
  2. Cookie存储在HTTP客户端,HTTP请求头Cookie传给给HTTP服务端;
  3. HTTP服务端通过响应头Set-Cookie管理HTTP客户端存储的Cookie;
  4. Cookie数据需要在HTTP会话中传递,所以Cookie数据必须小。

1.3 Cookie的限制

大小、数量:

  1. 为了防止滥用cookie导致HTTP请求头过大,各浏览器对一个domain的cookie数据和cookie大小都有限制。
  2. Don't exceed 50 cookies per domain, and don't exceed 4093 bytes per domain

Browser Cookie Limits

  1. 如果只是想实现浏览器端的数据持久化,可以使用其他Web存储(localstorage, sessionstorage,indexDB等)

字符集

  1. cookie的namevalue是用户自定义的,但是需要都采用US-ASCII字符集;
  2. 有些字符不能作为name 如空格,tab, ) < > @ , ; : \ " / [ ] ? = { }等
  3. 有些字符作为value需要转移; 如分号,空格,其他非US-ASCII字符集的字符。
  4. 一般通过decodeURIComponentvalue进行转义;

二、Cookie的构成

2.1 Cookie属性

1. 核心属性:namevalue属性

2. 有效期属性:ExpiresMax-Age

  1. Secure 防止 Cookie 在传输过程中被窃取和篡改.

  2. SameSite 可以让 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。

2.2 HTTP响应Set-Cookie

  1. HTTP服务向客户端发送cookie数据,一个Set-Cookie对应一个cookie数据;
  2. Cookie各个属性通过;隔开(其中分号后面是0个或多个空格);

2.3 HTTP请求Cookie

  1. 客户端向服务发送当前domain可以访问的并且有效的cookie列表。多个cookie通过;隔开(其中空格可选,0个或者多个);

三、use-cookies-securely

  1. domain不能用作安全措施;

四、跨域

Cookie并不严格遵循浏览器同源策略,而是同站(SameSite),即主域一致就可以共享。

  1. 子Domain可以访问父Domain下的cookie(反之不行,兄弟domain也不行);
  2. Cookie的作用域跟端口无关,即不同端口的相同域名和path可以共享cookie。

五、Cookie 与 Session 的区别

参考

  1. RFC6265
  2. MDN HTTP Cookies
  3. 掘金:预测最近面试会考 Cookie 的 SameSite 属性
yaofly2012 commented 4 years ago

浏览器操作Cookie

  1. 客户端操作Cookie受限比较多些(作用域,httpOnly)。
  2. document.cookie表示当前文档能访问的cookie(这也是为啥cookie熟悉不是在window对象下)。

document.cookie

// 读所有的cookies
allCookies = document.cookie;

// 写单个cookie
document.cookie = newCookie;
  1. document.cookie作为右值时,则返回当前domain下可以访问且有效的cookie(key-value对)字符串列表。
    "_test_k1=hello1; _test_k3=world3; _test_session=session%20cookie;"
  2. document.cookie作为左值时,表示对单个cookie进行操作(新增,编辑,删除)。
  3. 不得不说通过document.cookie操作cookie挺麻烦的。
    • 不能读取单个cookie;
    • 写cookie必须先转成字符串,缺乏语义话的操作API;
    • 不过document.cookie倒是很方便在HTTP请求头添加Cookie头时取值。

提取单个cookie值

document.cookie返回的是所有的cookie列表字符串,如果要读取单个cookie一般有两种方式:

  1. 利用正则表达式
  2. 先把document.cookie转成对象,再读取。 30-seconds-of-code parseCookie
    const parseCookie = str =>
    str
    .split(';')
    .map(v => v.split('='))
    .reduce((acc, v) => {
      acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
      return acc;
    }, {});

    社区也有其他cookie解析库npm cookie

yaofly2012 commented 4 years ago

服务端操作Cookie

1. 基于Nodejs HTTP服务端

  1. 采用HTTP的语法规则+借助第三方的cookie操作库

2. 基于Expressjs库 HTTP服务端

expressjs提供了更加语义化的操作API。

  1. req.cookies
  2. res.cookie(name, value [, options])
  3. cookie-parse中间件内部还是依赖cookie
    • Express还支持对cookie的value进行加密、解密处理(缺点就是影响性能)
yaofly2012 commented 4 years ago

Cookie安全

  1. XSS
  2. CSRF
    • SameSite

SameSite