面试官:说下Cookie和Session的关系和区别,以及Token是什么?

在技术面试中,经常被问到"Cookie和Session的区别",大家都知道一些,Session比Cookie安全,Session是存储在服务器端的Cookie是存储在客户端的,然而如果让你更详细地说明,恐怕就不怎么清楚了。

cookie 是浏览器和服务器之间存储和传输数据的一种方式,session 是服务器端的会话管理机制,token 是一种身份验证的方式,而 JWT 是 token 的一种具体实现形式。

1.什么是HTTP

首先要先介绍什么是HTTP。

HTTP:超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

HTTP 是无状态协议,说明它不能以状态来区分和管理请求和响应。如何判断两次请求的是同一个人?就好比用户在页面 A发起请求获取个人信息,然后在另一个页 面同样发起请求获取个人信息,我们如何确定这俩个请求是同一个人发的呢?也就是说,服务器单从网络连接上无从知道客户身份。

为了解决这种问题,我们就迫切需要一种方式知道发起请求的客户端是谁?此时,cookie、token、session 就出现了,它们就可以解决客户端标识的问题,在扩大一点就是解决权限问题。

什么是cookie

Cookie翻译过来是' 小甜饼',Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,实际上Cookie是服务器在客户端或者说浏览器中存储的一小段文本,并随着每次请求发送到服务器。

Cookie技术通过请求和响应报文中写入Cookie信息来控制客户端的状态。

Cookie会根据响应报文里的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie。当下客户端再向服务端发起请求时,客户端会自动在请求报文中加入Cookie值之后发送出去.

之后服务端发现客户端发送过来的Cookie后,会检查是那个客户端发送过来的请求,然后对服务器上的记录,最后得到了之前的状态信息。

cookie 主要有以下属性:

属性名称 属性含义
name cookie 的名称
value cookie 的值
comment cookie 的描述信息
domain 可以访问该 cookie 的域名
expires cookie 的过期时间,具体某一时间
maxAge cookie 的过期时间,比如多少秒后 cookie 过期
path cookie 的使用路径
secure cookie 是否使用安全协议传输,比如 SSL 等
version cookie 使用的版本号
isHttpOnly 指定该 Cookie 无法通过 JavaScript 脚本拿到,比如 Document.cookie 属性、XMLHttpRequest 对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie。

我们介绍了 cookie,那么我们是如何通过 cookie 来实现用户确定或者权限的确定呢?

我们就以一个普通网站的用户登录操作以及后续操作为例,主要过程可以简单用下图表示:

从上图中可以看到使用 cookie 进行用户确认流程是比较简单的,大致分为以下几步:

  1. 客户端发送请求到服务端(比如登录请求)。

  2. 服务端收到请求后生成一个 session 会话。

  3. 服务端响应客户端,并在响应头中设置 Set-Cookie。Set-Cookie 里面包含了 sessionId,它的格式如下:Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用来标识客户端的,类似于去饭店里面,服务员给你一个号牌,后续上菜通过这个号牌来判断上菜到哪里。

  4. 客户端收到该请求后,如果服务器给了 Set-Cookie,那么下次浏览器就会在请求头中自动携带 cookie。

  5. 客户端发送其它请求,自动携带了 cookie,cookie 中携带有用户信息等。

  6. 服务端接收到请求,验证 cookie 信息,比如通过 sessionId 来判断是否存在会话,存在则正常响应。

cookie 主要有以下特点:

  • cookie 存储在客户端
  • cookie 不可跨域,但是在如果设置了 domain,那么它们是可以在一级域名和二级域名之间共享的。

3.什么是 session?

在上一节中,我们通过 Cookie 来实现了用户权限的确认,在其中我们提到了一个词:session。顾名思义它就是会话的意思,session 主要由服务端创建,主要作用就是保存 sessionId,用户与服务端之间的权限确认主要就是通过这个 sessionId。

简单描述下 session:

session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。

总之每一个客户端与服务端连接,服务端都会为该客户端创建一个 session,并将 session 的唯一标识 sessionId 通过设置 Set-Cookie 头的方式响应给客户端,客户端将 sessionId 存到 cookie 中。

通常情况下,我们 cookie 和 session 都是结合着来用,当然你也可以单独只使用 cookie 或者单独只使用 session,这里我们就将 cookie 和 session 结合着来用。

我们可以在修改一下整个请求过程图,如下所示:

4.cookie 和 session 的区别?

前面两节我们介绍了 cookie 和 session,它们两者之间主要是通过 sessionId 关联起来的,所以我们总结出:sessionId 是 cookie 和 session 之间的桥梁。我们日常的系统中如果在鉴权方面如果使用的是 cookie 方式,那么大部分的原理就和我们前面说的一样。

或者我们可以换个说法,session 是基于 cookie 实现的,它们两个主要有以下特点:

  • session 比 cookie 更加安全,因为它是存在服务端的,cookie 是存在客户端的。
  • cookie 只支持存储字符串数据,session 可以存储任意数据。
  • cookie 的有效期可以设置较长时间,session 有效期都比较短。
  • session 存储空间很大,cookie 有限制。

系统想要实现鉴权,可以单独使用 cookie,也可以单独使用 session,但是建议结合两者使用。

5.token 是什么?

前面我们说的 sessionId 可以叫做令牌,令牌顾名思义就是确认身份的意思,服务端可以通过令牌来确认身份。

cookie+session 是实现认证的一种非常好的方式,但是凡事都有两面性,它们实现的认证主要有以下缺点:

  • 增加请求体积,浪费性能,因为每次请求都会携带 cookie。

  • 增加服务端资源消耗,因为每个客户端连接进来都需要生成 session,会占用服务端资源的。

  • 容易遭受 CSRF 攻击,即跨站域请求伪造。

那么为了避免这些缺点,token 方式的鉴权出现了,它可以说是一个民间的认证方式,但是不得不说它带来了非常多的好处。

token 的组成:

token 其实就是一串字符串而已,只不过它是被加密后的字符串,它通常使用 uid(用户唯一标识)、时间戳、签名以及一些其它参数加密而成。我们将 token 进行解密就可以拿到诸如 uid 这类的信息,然后通过 uid 来进行接下来的鉴权操作。

前面我们说 cookie 是服务端设置了 set-cookie 响应头之后,浏览器会自动保存 cookie,然后下一次发送请求的时候会自动把 cookie 携带上。但是我们说 token 算是一种民间的实现方式,所以说浏览器自然不会对它进行处理。token 主要是由服务器生成,然后返回给客户端,客户端手动把 token 存下来,比如利用 localstorage 或者直接存到 cookie 当中也行。

token 认证流程:

  1. 客户端发起登录请求,比如用户输入用户名和密码后登录。

  2. 服务端校验用户名和密码后,将用户 id 和一些其它信息进行加密,生成 token。

  3. 服务端将 token 响应给客户端。

  4. 客户端收到响应后将 token 存储下来。

  5. 下一次发送请求后需要将 token 携带上,比如放在请求头中或者其它地方。

  6. 服务端 token 后校验,校验通过则正常返回数据。

用图表示大致如下:

我们所说的Token,通常指JWT(JSON Web TOKEN)。JWT是一种轻量级的安全传输方式,用于在两个实体之间传递信息,通常用于身份验证和信息传递。

JWT是一个字符串,如下图所示,该字符串由三部分组成,三部分由.分隔。三个部分分别被称为

  • header(头部)
  • payload(负载)
  • signature(签名)

各部分的作用如下

  • Header(头部)

    Header部分是由一个JSON对象经过base64url编码得到的,这个JSON对象用于保存JWT 的类型(typ)、签名算法(alg)等元信息,例如

    json 复制代码
    {
      "alg": "HS256",
      "typ": "JWT"
    }
  • Payload(负载)

    也称为 Claims(声明),也是由一个JSON对象经过base64url编码得到的,用于保存要传递的具体信息。JWT规范定义了7个官方字段,如下:

    • iss (issuer):签发人
    • exp (expiration time):过期时间
    • sub (subject):主题
    • aud (audience):受众
    • nbf (Not Before):生效时间
    • iat (Issued At):签发时间
    • jti (JWT ID):编号

    除此之外,我们还可以自定义任何字段,例如

    json 复制代码
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
  • Signature(签名)

    由头部、负载和秘钥一起经过(header中指定的签名算法)计算得到的一个字符串,用于防止消息被篡改。

总结

虽然前面解释 cookie、session、token 用了不少口舌,但是归根结底啊,它们的目的都是一样的:鉴权和认证。

鉴权认证方式 特点 优点 缺点
cookie 1. 存储在客户端。 2. 请求自动携带 cookie。 3. 存储大小 4KB。 1. 兼容性好(老技术)。 2. 易实现(自动携带和存储)。 1. 需解决跨域问题(如多服务器共享)。 2. 易受 CSRF 攻击。 3. 客户端存储不安全。
session 1. 存储在服务器端。 2. 存储大小无限制。 1. 查询快(内存操作)。 2. 结合 cookie 易实现鉴权。 3. 服务器存储更安全。 1. 消耗服务器资源(每个客户端创建 session)。 2. 占据存储空间(完整用户信息)。
token 1. 体积小。 2. 存储位置自由。 1. 安全(仅含用户 id)。 2. 节省服务器内存(仅存 id)。 3. 跨域方便(多服务器共享)。 1. 查询慢(需数据库查询用户 id)。
相关推荐
浪遏9 分钟前
我的远程实习(六) | 一个demo讲清Auth.js国外平台登录鉴权👈|nextjs
前端·面试·next.js
拉不动的猪2 小时前
vue与react的简单问答
前端·javascript·面试
牛马baby2 小时前
Java高频面试之并发编程-02
java·开发语言·面试
yuanbenshidiaos3 小时前
面试问题总结:qt工程师/c++工程师
c++·qt·面试
uhakadotcom3 小时前
Langflow:打造AI应用的强大工具
前端·面试·github
uhakadotcom3 小时前
🤖 LangGraph 多智能体群集
面试·架构·github
uhakadotcom4 小时前
Caddy Web服务器初体验:简洁高效的现代选择
前端·面试·github
uhakadotcom4 小时前
NVIDIA Resiliency Extension(NVRx)简介:提高PyTorch训练的容错性
算法·面试·github
专业抄代码选手5 小时前
【JS】instanceof 和 typeof 的使用
前端·javascript·面试
雷渊5 小时前
深入分析mybatis中#{}和${}的区别
java·后端·面试