cookie

# cookie

  • cookie就是用来解决状态管理的问题。
    • HTTP协议是一个无状态的协议,从而导致服务器接收客户端的请求,返回一个响应,如果没有记录关于客户端的任何信息,那么等下次客户端再次发起请求的时候,服务器并不知道客户端是谁。
    • 而cookie是存储在浏览器的一个小小文本文件,可以附着在HTTP请求上,在浏览器和服务器之间飞来飞去,可以携带用户信息。

cookie

一个请求首部,其中含有先前由服务器通过 Set-Cookie 首部投放并存储到客户端的 HTTP cookies。(字符串信息)

这个首部可能会被完全移除,例如在浏览器的隐私设置里面设置为禁用cookie。

查看:Application->Storage->Cookies

[TOC]

# 一、cookie特性

# 1.1 前端数据存储

# 1.1.1 cookie的有效期

  • Expires
    • 俗称过期时间,可以理解成截止日期,用的是绝对时间。
    • 默认一个cookie的生命周期就是在关闭浏览器的时候结束。
  • Max-Age(优先级较Expires高)
    • 相对时间,单位是秒。
  • 兼容问题:
    1. Chrome:new Date()->GMT时间(北京标准时间GMT+0800) IE:new Date()->UTC时间(北京标准时间UTC+0800)
    2. Chrome:cookie的过期时间->GMT时间 IE和FF:cookie的过期时间->本地时间写入cookie的过期时间 查看chrome的cookie有效期时默认加8小时
    3. UTC:根据原子钟来计算时间,50亿年误差一秒 GMT:根据地球的自转和公转来计算时间

# 1.1.2 cookie的作用域

让浏览器仅发送给特定的服务器和URI,避免被其他网站盗用。

  • Domian:指定cookie所属的域名。
  • Path:指定cookie所属的路径。
    • 现实中为了省事,通常Path就用一个“/”或者直接省略,表示域名下的任意路径都允许使用cookie,让服务器自己去挑。

# 1.1.3 cookie的安全性

  • HttpOnly
    • 表明此cookie只能通过浏览器HTTP协议传输,禁止其他方式访问。浏览器的JS引擎就会禁用document.cookie等一切相关API,脚本攻击也就无从谈起了。
  • SameSite
    • 可以防范CSRF。
    • 设置成“SameSite=Strict”可以严格限定Cookie不能随着跳转链接跨站发送,而“SameSite=Lax"则略宽松一点,允许GET/HEAD等安全方法,但禁止POST跨贴发送。
  • Secure
    • 表示Cookie仅能用HTTPS协议加密传输,明文的HTTP协议会禁止发送。但Cookie本身不是加密,浏览器里还是以明文的形式存在。

# 1.2 前端可读写

  • 服务端向客户端发送cookie
Set-Cookie: <cookie-name>=<cookie-value>;(可选参数1);(可选参数2)
1
  • 客户端设置cookie
document.cookie = "<cookie-name>=<cookie-value>;(可选参数1);(可选参数2)"
1

# 1.3 遵守同源策略

可以通过特殊设置达到cookie跨域访问

# 二、cookie类型

  1. 当前网站本身设置的cookie
  2. 其他域来源的第三方cookie:跟踪你的使用信息

# 三、大小限制

  1. 每个cookie所存放的数据不能超过4k。
  2. 如果cookie字符串长度超过4k,则该属性将返回空字符串。

# 四、cookie 作用

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

# 4.1 身份识别

  1. 存储个性化设置

    1. 选择了怎样的皮肤
    2. 上次停留的页面
    3. 一个菜单是打开还是关闭
  2. 存储未登录时用户唯一标识

    1. 生成随机的标识区分你是你,我是我
  3. 存储已登录用户的凭证

    1. 过程:

      1. 前端提交用户名和密码
      2. 后端验证用户名和密码
      3. 后端通过http头设置用户凭证
      4. 后续访问时后端先验证用户凭证
    2. 方法:

      1. 用户ID:给用户发一个号

        • 存在巨大的安全隐患:userId=1用户通过纂改document.cookie="userId=2"模拟用户2登录
      2. 用户ID+签名:

        • 签名是不伪造的,只有后台才知道密钥
        • 通过用户ID去验证签名是否一致,可防止篡改
        • 可能被盗取
      3. SessionId:

        • 并不存放真正的数据,存放的数据与用户无关
        • 随机的字符串,防篡改防盗取,只给前端一个随机字符串标识
        //session.js
        var session = {};
        var cache = {};
        
        session.set = function(userId, obj) {
            var sessionId = Math.random();
            if (!cache[sessionId]) {
                cache[sessionId] = {};
            }
        
            cache[sessionId].content = obj;
        };
        
        session.get = function(sessionId) {
            return cache[sessionId] && cache[sessionId].content;
        };
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
      4. Token

  4. 存储业务其他数据

    1. 根据具体需求缓存数据

# 4.2 广告跟踪

这种cookie不是由访问的主站存储的,而是由广告图片背后的广告商给你贴上cookie小纸条,以方便精准打击,所以也叫第三方cookie(third-party)。

# 五、安全问题

# 5.1 cookie与XSS

  1. XSS可能偷取cookie:可以用js的document.cookie访问cookie
    1. http-only的cookie不会被偷

# 5.2 cookies与CSRF

  1. CSRF利用了用户Cookies:目标网站会带上用户的cookie
    1. 攻击站点无法读写cookies
      1. 最好能阻止第三方使用cookie:验证码

# 5.3 cookie安全策略

  1. 签名防篡改
  2. 私有变换(加密):用户不知道值代表的含义
  3. http-only防XSS
  4. secure防传输过程中的监听
  5. same-site防CSRF

# 六、session

参考教程:你真的了解 Cookie 和 Session 吗 (opens new window)

# 6.1 什么是session

  • Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。
  • 当访问增多时,Session会较大地占用服务器的性能。考虑到减轻服务器性能方面,应当适时使用Cookie
  • Session的运行依赖Session ID,而Session ID是存在 Cookie 中的。也就是说,如果浏览器禁用了Cookie,Session也会失效(但是可以通过其它方式实现,比如在url中传递Session ID,即sid=xxxx)。
  • session保存在服务器,客户端不知道其中的信息。

# 6.2 cookie与session的不同

cookie session
作用范围 保存在浏览器 保存在服务器
存储类型 只能保存 ASCII 任意数据类型
有效期 较长,比如用于默认登录功能 较短,浏览器关闭或超时就失效
安全性
存储大小 4k 远高于4k

# 6.3 cookie和session的由来

浏览器是没有状态的(HTTP 协议无状态),这意味着浏览器并不知道是张三还是李四在和服务端打交道。这个时候就需要有一个机制来告诉服务端,本次操作用户是否登录,是哪个用户在执行的操作,那这套机制的实现就需要 Cookie 和 Session 的配合。

cookie-seesion

  • SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

# 6.4 禁用cookie

既然服务端是根据 Cookie 中的信息判断用户是否登录,那么如果浏览器中禁止了 Cookie,如何保障整个机制的正常运转。

# 6.4.1 SessionID

每次请求中都携带一个 SessionID 的参数,也可以 Post 的方式提交,也可以在请求的地址后面拼接 xxx?SessionID=123456...

# 6.4.2 Token机制

参考教程:干掉状态:从session到token (opens new window)

Token 机制多用于 App 客户端和服务器交互的模式,也可以用于 Web 端做用户状态管理。

Token 的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。Token 机制和 Cookie 和 Session 的使用机制比较类似。

当用户第一次登录后,服务器根据提交的用户信息生成一个 Token,响应时将 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次登录验证。

token

  • 服务器不用保存sessionId,只用生成token,然后验证token,用CPU的计算时间来获取session的存储空间。
  • 机器集群可以轻松地做水平扩展,用户访问量增大,直接加机器就行了。