浏览器系列 — cookie、session、Token、JWT及对应的登录态机制

吐槽君 分类:javascript

首先清楚三个概念:

认证

  • 通俗地讲就是验证当前用户的身份,证明“你是你自己”
  • 互联网中的认证:
    • 用户名密码登录
    • 邮箱发送登录链接
    • 手机号接收验证码
    • 只要你能收到邮箱/验证码,就默认你是账号的主人

授权

  • 用户授予第三方应用访问该用户某些资源的权限
    • 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限)
    • 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息)
  • 实现授权的方式有:cookie、session、token、OAuth

凭证

  • 实现认证和授权的前提是需要一种媒介(证书) 来标记访问者的身份
    • 相当于每个人的身份证
比如掘金会有两种模式:`游客模式``登录模式`。
游客模式下,可以正常浏览网站上面的文章,一旦想要点赞/收藏/分享文章,就`需要登录或者注册账号`。
当用户登录成功后,服务器会给该用户使用的浏览器颁发一个令牌(`token`),此令牌用来`表明你的身份``每次`浏览器发送请求时`会带上`这个令牌,就可以使用游客模式下无法使用的功能
 

用户登录方案

  • Cookie + Session 作登录态
  • Token 作登录态
  • OAuth 第三方登录

Cookie + Session 作登录态

前言引入

我们以 <商城及购物车> 为例子作引入:

对于商城首页,所有用户浏览的商品都是一样的情况下,用户不用登录也可以访问。当时如果用户选择商品加入购物车添加到收藏夹的时候,我们就需要有可以标识用户身份的凭证,这就可以采用 cookie + session 的机制来作登录态

什么是 session

用户在某个网站首次登录,此时浏览器发起请求给服务端,服务端会为这次请求临时开辟一块内存空间,存的便是session对象,session对象存的内容就是记录用户的一些状态行为记录

那么问题来了,服务端如何知道收到的请求是哪个用户操作浏览器发起的呢?于是cookie就出场了

什么是 cookie

简单来说,cookie是服务器通过在响应头中的Set-Cookie字段发送到用户的浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。它用来保持用户登录状态,和session配合使用可以用来交流清楚是哪位用户

关于cookie的详细内容见 浏览器系列 -- 本地存储

cookie 和 session 的区别

  • 存放位置:cookie在浏览器,session在服务端(一般是在内存中)
购物车的数据一般放在`数据库`中,session的目的不是存购物车的数据,而是作为让服务端知道是哪位用户的`工具`罢了。
为什么session不存购物车的数据,因为cookie到期用户被退出登录,重新登录后session被替代掉,意味着购物车的数据将被清空
 
  • 安全系数:cookie安全系数低,session安全系数高
  • 有效时间:cookie看设置的有效期,如果没有设置则是窗口关闭就消失,session在内存也是窗口关闭就消失,在数据库里理论上可以很久
  • 性能方面:cookie不会造成服务端压力大,用户数过大时,session会造成服务器压力大
  • 存储内容:cookie存的数据一般是用户昵称账号等一些非隐私数据,而session一般存密码、一些ID之类的隐私数据
  • 存储的数据类型:cookie是字符串类型,而session可以是任何类型,主要是键值对的哈希表类型Object类型

cookie和session的联系

两者都是为了跟踪浏览器用户身份的会话方式,两者相互配合可以作登录态

接下来看一下 cookie 和 session 是如何配合作登录态的:

实现流程

  • 用户首次登录

image.png
用户首次登录后,服务器服务端会创建该用户对应的sessionsession id,我把session比喻成一把,把session id比喻成开这把锁的一把钥匙,然后服务端把这把钥匙通过发送响应头的方式(将session id放在响应头header的Set-Cookie字段里面),浏览器收到后把session id放在cookie里面,这时cookie的有效期就等于这把钥匙的有效期,也就是说cookie一旦过期,登录态就作废,表示用户退出登录(属于被动退出)

  • 登录之后的访问

image.png
用户当前处于登录态,然后访问该网站并发起http请求(比如将商品加入购物车),此时浏览器会自动携带该用户的cookie,(可能是拿取存放session id的cookie),服务端这边要是得知这把锁被打开了,就跑去数据库拿该用户存在数据库的数据(购物车)并返回。但要是打不开,比如cookie过期,服务器会返回状态码401,浏览器收到之后会要求用户重新输入账号密码登录

Token 作登录态

为什么选择使用token代替session+cookie作登录态?

  • 服务器压力大:通常session是存储在内存中的,用户数增多时,内存空间被挤爆
  • cookie过期代表用户被退出登录,体验感极差
  • cookie容易遭受CSRF攻击
  • 如果禁用cookie,就用token来作登录态

分类

  • acesss token:访问资源接口时所需要的资源凭证
access token 基本组成部分:
1. uid (用户唯一的身份标识)
2. time (当前时间的时间戳)
3. sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
 
  • refresh token:专用于刷新 access token 的 token
如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户`重新输入`登录用户名与密码,会很麻烦
 

如何使用 access token 作登录态

image.png

  1. 用户首次登录,服务器对用户名和密码进行检验,验证成功后生成加密token并返回(响应头里面),浏览器收到token后放在cookielocalstorage里面【注意此时服务器不保存token】
  2. 用户当前处于登录态,然后访问该网站并发起http请求(比如将商品加入购物车),此时携带token放在请求头里面发送给服务器
  3. 服务器根据JWT算法解密和检验 token ,验证成功,保持登录态,要是验证失败,会在响应头返回状态码401,浏览器这边收到会使用 refresh token 刷新 access token

这波是用解析 token 的时间 session 的存储空间,减轻服务器的压力

关于JWT算法:简单来说就是对token进行解密,解密后判断是否可用(/过期),直接表明登录态是否保持

如何使用 refresh token 刷新 access token

要是 access token 验证失败,则浏览器这边需要对 access token 进行更新,方法是使用 refresh token

image.png

  • access token 的有效期比较短(比如是一周), refresh token 的有效期比较长(比如一个月),当 acesss token 过期失效但 refresh token 未过期,则使用 refresh token 就可以获取到新的 token
  • 如果 refresh token 也失效了,用户就只能重新登录
  • refresh token 及过期时间是存储在服务器的数据库中,只有在需要申请新的 acesss token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 session 一样一直保持在内存中以应对大量的请求

OAuth 第三方登录

image.png

OAuth 机制实现流程

这里以微信开放平台的接入流程为例:

image.png

  • 网站运营者申请账户
  1. 首先,a.com 的运营者需要在微信开放平台注册账号,并向微信申请使用微信登录功能。
  2. 申请成功后,得到申请的 appidappsecret
  • 用户登录并授权
  1. 用户在 a.com 上选择使用微信登录。
  2. 这时会跳转微信的 OAuth 授权登录,并带上 a.com 的回调地址。
  3. 用户输入微信账号和密码,登录成功后,需要选择具体的授权范围,如:授权用户的头像、昵称等。
  • 微信生成临时票据
  1. 授权之后,微信会根据拉起 a.com?code=123 (或重定向到第三方),带上临时票据 code
  • 网站向微信索取 access token
  1. 获取 code 之后, a.com 会拿着 code 、appid、appsecret,向微信服务器申请 token,验证成功后,微信会下发一个 token。
  2. 有了 access token 之后, a.com 就可以用 access token 调用微信接口,拿到对应的微信用户头像,用户昵称等信息了。
  3. a.com 提示用户登录成功,并将登录状态写入 cookie,以作为后续访问的凭证。

其他平台的接入方式可以去对应得官方文档查看,流程基本类似。

参考文章

  • 傻傻分不清之 Cookie、Session、Token、JWT
  • 前端常见登录实现方案 + 单点登录方案
  • 看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了

回复

我来回复
  • 暂无回复内容