# 前言

  1. 基于HTTP的前端鉴权背景
  2. cookie为什么是最方便的存储方案,有哪些操作cookie的方式
  3. session方案是如何实现的,有什么问题
  4. token方案是如何实现的
  5. session和token的区别

# HTTP无状态

  • HTTP请求和响应间无法维护状态,不知道前后的请求都发生了什么
  • 【用户登录、发布、评论、加购】场景需要维护状态
  • 前端存储涉及到【一发、一存、一带:入学第一天会录入你的身份及账户信息,给你发个卡,今后进出学校都用这张卡】
  • 发:服务端发送给前端
  • 存:前端存储:挂在全局变量上(体验卡,一刷新页面就没了)| cookie/localStorage(会员卡,无论怎么刷新,只要浏览器没有清理或过期,就会一直持有这个状态)
  • 带:前端需要携带数据
  • 借助HTTP头、浏览器能力,用来在客户端保存用户身份信息的
  • 过程:服务端通过Set-Cookie字段发送到浏览器并保存在本地,浏览器发起请求时,把cookie通过HTTP请求头的Cookie字段发送给服务器
  • 配置 Domain / Path:指定哪些主机可以接收cookie【不能拿北大的卡进清华】
  • 配置 Expires / Max-Age:过期时间/有效期【毕业了卡就不能使用了】
  • 配置 HttpOnly / Secure:【不带卡套就不让刷】
    • HttpOnly:阻止JS的访问,缓解XSS
    • Secure:只会通过被HTTPS加密后的请求
  • 配置 SameSite:要求浏览器在跨站时是否能发送,阻止CSRF

# session

  • session登录/验证流程:
    • 浏览器发送账号密码,服务端查询用户库,校验用户身份
    • 服务端把用户登录状态设置为session,生成sessionID,通过登录接口返回并设置到cookie上(Set-Cookie:sessionID)
    • 浏览器再次请求接口,携带cookie:sessionID
    • 服务端查sessionID校验session,成功后做业务处理返回结果
  • 存储方式:服务端只是给cookie设置一个sessionID,session的具体内容需要通过Redis/内存/数据库进行存储
  • 过期和销毁:把存储的session数据销毁
  • session分布式问题:服务端是集群,用户请求过来后会走一次负载均衡,不一定到固定一个服务器上,一旦后续请求时服务器宕机或到其他服务器,session不就会失效了吗
    • 存储角度:把session集中存储,存到一个库
    • 分布角度:让相同IP的请求在负载均衡时都到同一台服务器上【Nginx配置ip_hash】
  • 缺点:session的维护给服务端造成很大困扰(需要找地方存储,又要考虑分布式问题,甚至需要启用一套Redis集群)

# token

  • 不在服务端存储,直接打包到cookie中,每次核验携带的cookie【想进学校,直接比对卡上的信息】
  • 登录/验证流程:
    • 浏览器发送账号密码,服务端校验,从用户库中获得用户信息
    • 把用户信息、token配置编码成token,设置到cookie上(Set-Cookie:token)
    • 浏览器再次请求接口,携带cookie:token
    • 服务校验token,成功后做业务处理返回结果
  • 避免被篡改:给token加签名(HMACSHA256),但会额外增加cookie数量而且数据本身也没有规范格式

# JWT

  • JSON Web Token:定义了传递JSON信息的方式,token字符串生成方式

# session与cookie

  • session:客户端存cookie,数据存储在服务端
  • token:客户端存储在哪都行,数据存储在token

# 总结

  • HTTP是无状态的,为了维持前后请求,需要前端存储标记
  • cookie是一种完善的标记方式,通过HTTP头/JS操作,有对应的安全策略,是大多数状态管理的基石
  • session是一种状态管理方案,前端通过cookie存储id,后端存储数据,需要考虑分布式问题
  • token是另一种状态管理方案,后端不需要存储数据,数据全部存储于前端。token编码技术通常基于base64/增加加密算法防篡改,jwt是一种成熟的编码方案
  • session与token的区别在于[用不用cookie]与[后端存不存]

参考博客:前端鉴权必须了解的 5 个兄弟:cookie、session、token、jwt、单点登录