Cookie、Session、LocalStorage

328 阅读5分钟

状态保持

自从我登录一次用户名和密码以后,很长时间都不需要再输入了,这个活不是HTTP干的,因为他是无状态的,他不知道是谁在访问服务器,他自己不会记用户名和密码的事

那到底是谁保持的登录状态呢?有以下几种技术可以实现,核心的概念是存储

保存在数据库

注册时的用户名和密码被b站保存到数据库,下次登录的时候b站会根据用户输入的用户名和密码与数据库做比对,成功就返回响应的页面。

浏览器设置

要是b站不想让已经登录过的用户再次输入账号密码,假设1天后需要重新输入账号密码,需要使用到存储,即设置让用户可以选择记住账号密码,让浏览器干这个事,但是风险很高,加上HTTP无状态问题

Cookie

是一种存储在浏览器的数据。属于HTTP协议里的,由服务器向客户端发送的一段token,形式为Set-Cookie:token,这个token的特殊之处在于浏览器在后续的所有请求中自动带上账号密码,以做到保持登录。

实现每次HTTP请求都自动带数据给服务器的技术就是Cookie,形式为:Cookie:token

LocalStorage属于手动带上的,而Cookie属于浏览器自动把cookie带到同一域名的请求。

Cookie基本流程

浏览器发出HTTP请求到服务器,服务器会进行Cookie设置,即Set-Cookie,里面有名和值两个属性,发给浏览器后,保存起来。以后浏览器以后发送的每个请求都会自动附上Cookie。

Session

服务器自己定义的保存在数据库里的数据。

基于打开浏览器就能看到保存了哪些Cookie,即账号密码放在Cookie里是很不安全的,这个问题由Session解决,浏览器访问服务器就是会话的开始,不同的网站对与每个用户的会话都设定了时间(结束会话的时间)以及唯一的ID,即Session ID(一串没有规律的字符串),Session ID存在Cookie里。

Session基本流程

访问b站的过程:用户输入账号密码登录发送给b站服务器,b站服务器核对无误后,创建一个Session ID和会话结束时间,用Set-Cookie发送给浏览器(会进行签名),即此时的Cookie里有Session ID和有效期(会话结束时间对应设置为Cookie的有效期),浏览器拿到Cookie后保存Session ID(没有规律的字符串),而没有保存账号密码,黑客此时如果获取并修改了Session ID,基于之前的签名,服务器也就不能识别这个字符串了。浏览器以后的每次访问都会自动发送这个Session ID给服务器,直到Cookie的有效期失效之后,浏览器自行删除Cookie,即会话结束。

JWT

随着用户量的日益增多,在特定时间有大量用户访问服务器的时候,服务器就需要存储大量的Session ID,对于多台服务器又需要分享Session ID给其他服务器,虽然数据库也能存储Session ID,但是数据库的崩溃就会影响服务器获取Session ID,基于以上的各种原因和需求,出现了一种叫JWT的技术。

JSON Web Token

Token就是加密字符串,把userid加密发给前端。JWT = 加密(uid)

用户登录网页后,服务器自动生成一个JWT,不需保存JWT,只需保存其签名的密文,把JWT发送给浏览器,可以让浏览器以Cookie(或Storage)的形式存储JWT,也就是存储在用户一边。 用户每次发送请求都会把这个JWT发给服务器。服务器需要保存一段密码。

JWT组成

header.payload.signature

// header 声明需要用什么算法来生成签名  alg
// payload 特定的数据:有效期   {uid:1}
// header+payload 经由 Base64 编码  
// s=加密(私钥, base64(header), base64(body))

上节中提到的服务器保存的一段密码,结合经由 Base64 编码进行算法运算,得到签名信息

JWT用法

用户登录时,前端发了一个请求:POST /JWT ,内部含账号密码;

服务器识别后响应一个JWT,内容有3个部分组成,前端主要关注第2部分内容,因为含uid信息,前端拿到JWT以后,会存到LocalStorage里面,配置axio库,使其请求的header都带上JWT

const jwt = localStorage.getItem("jwt");
if (jwt) {
    config.headers!.Authorization = `Bearer ${jwt}`;
}

接着再次登录时,发请求:GET /user,服务器会看请求Authorization中的JWT是否带上,如有就会解开,对比上一步响应的第3部分s中的uid与前端请求中解出来的uid是否一致,一致则去数据库中读取user,转换为JSON,发给前端。

LocalStorage 本地存储

HTML 5提供的API,用于存储数据到本地。区别于定义变量的保存在内存中,LocalStorage是以字符串的形式保存在本地硬盘里的数据。


localStorage.setItem('obj'JSON.stringify(obj));

console.log(JSON.parse(localStorage.getItem('obj')))

image.png

localStorage.getItem('Goo');  // 2023

image.png

// 指定删除
localStorage.removeItem('Goo');

// 清空存储数据
localStorage.clear();
let obj = {
  name:"Vue",
  age: 7
}
localStorage.setItem('obj'JSON.stringify(obj));

console.log(JSON.parse(localStorage.getItem('obj')))

image.png

总结

Session是诞生并保存在服务器,由服务器主导一切;

Cookie是一种数据载体,把Session放在Cookie中送到客户端,Cookie跟随HTTP的每个请求发送出去;

Token是诞生在服务器,但保存在浏览器,由客户端主导一切,可以放在Cookie或者Storage里面,持有Token就像持有令牌一样可以运行访问服务器。

感谢

感谢b站技术蛋老师的精彩分享!

感谢陈皓 《你会做WEB上的用户登录功能吗?》一文

感谢饥人谷官网