HTTP 协议是无状态的,这意味着如果客户端每次要与服务端通信,都必须重新与服务端连接,客户端请求一次,服务端才会响应一次,每一次请求都与之前的请求无关。
这样会产生的问题:
为了解决这些问题,便诞生了 cookie
、token
、session
,他们可以“知道”发起请求的客户端是谁,进而解决客户端标识问题(权限问题)。
cookie
、token
、session
相当于赋予客户端身份证,我们可以通过“身份证”判断发起请求的是谁
cookie 是保存在客户端(浏览器)中的一小块数据,大小限制在 4KB 左右。目前 cookie 存储数据的方式逐渐被取代,原因如下:
受害者 ↓
<div align=center> <iframe class="aspect-ratio" src="https://player.bilibili.com/player.html?bvid=BV1VY4y1Q7LC&&page=1&as_wide=1&high_quality=1&danmaku=0" scrolling="no" border="0" frameborder="no" framespacing="0" high_quality=1 danmaku=1 allowfullscreen="true"> </iframe> </div>属性名 | 含义 |
---|---|
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 的操作流程很简单,大致分为以下几步:
客户端向服务端发起请求
服务端接收到请求,之后生成一个 session 会话
服务端响应客户端,并在想用投中设置 Set-Cookie
,里面包含了 sessionId
,格式为:
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
其中,sessionId 用来标识客户端
客户端收到服务端的请求,如果服务器给了 Set-Cookie
,name浏览器在下一次请求中就会在请求头上自动携带 cookie
客户端再次发起请求,并自动携带了 cookie,cookie 也携带了用户信息
服务端收到请求,验证 cookie 信息,比如通过 sessionId 来判断会话是否存在,存在继续响应,否则不响应
图解(来自图解 HTTP):
在浏览器操作 cookie 的操作使用较少,了解即可(别像老莱一样就可以了):
浏览器进入设置,搜索cookie,就可以进行上述操作了
如果要查看某个网页的 cookie 数据,可以点击地址栏左边的小锁,如图:
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 都是基于 sessionId 实现的。而 session 是基于 cookie 实现的,主要有以下特点:
如果想要实现鉴权,cookie 和 session 都可以单独使用,但是建议两者结合使用
服务端可以通过 token(令牌)来确认身份,可以解决 session 和 cookie 的缺点
token 其实就是一串字符串而已,只不过它是被加密后的字符串,它通常使用 uid(用户唯一标识)、时间戳、签名以及一些其它参数加密而成。我们将 token 进行解密就可以拿到诸如 uid 这类的信息,然后通过 uid 来进行接下来的鉴权操作。
前面我们说 cookie 是服务端设置了 set-cookie 响应头之后,浏览器会自动保存 cookie,然后下一次发送请求的时候会自动把 cookie 携带上。但是我们说 cookie 算是一种民间的实现方式,所以说浏览器自然不会对它进行成么处理。token 主要是由服务器生成,然后返回给客户端,客户端手动把 token 存下来,比如利用 localstorage 或者直接存到 cookie 当中也行。
对于服务端渲染前后端分离这两种开发模式来说,分别有着不同的身份认证方案: