cookie,session和token的区别和用途

这三者本质上不是同一个东西,但是它们都和维持状态信息有关。我们登陆一个账户以后,后续很长时间都不用再重新登录了,这是为什么呢?熟悉HTTP的都知道,HTTP是无状态的,也就是说这次你访问了服务器,然后关闭网页,然后你再次访问服务器,这时候服务器是不知道又是你来访问的,但是登录状态是保持的,这里就会用到上面所说的三个东西。

1.什么是状态信息?

当我们在浏览器网站登陆一个账号以后,如果我们希望访问后续页面都维持登录的状态,就需要用到cookiesessiontoken来进行实现。如果说没有使用上面任何一个技术,我们要维持用户的登录状态信息,是非常麻烦的,比如说发起一个登录的请求,把用户密码传到服务端,服务端进行验证,如果正确的话就要把用户名和密码再返回给前端,以维持登录的状态信息,那么后续请求的所有页面我们都需要带上用户名和密码。

这样做的话毫无疑问既不安全又不方便,所以我们就可以使用上面三种方法解决。

2.cookie

使用cookie技术的话,前端发起登录请求,把用户名密码发送给服务端进行验证,如果通过的话,服务端会进行cookie设置,也就是set-cookiecookie里会有用户的一些信息比如idname等等,然后响应到浏览器,浏览器会把这些信息都保存在cookie上,保存以后呢访问后续页面都会自动带上cookie,这样呢就维持了页面的登录状态。如果不设置有效期的话,默认是关闭浏览器以后cookie就会失效,再次打开就要重新登录。

cookie的优点呢就是能够维持用户的登录状态。

那如果只用cookie来存储状态信息呢其实是会有很多问题的。

首先是会有安全的风险,因为cookie是存储在客户端的,所以用户是可以去篡改cookie的,对于服务器来说,它只会根据请求的cookie信息去获取当前登录的用户,所以一旦被篡改的话就不能保证安全性。

我们可以用数据签名的方式来实现,我们把所有数据链接起来拼接存在服务器里的密令,取Hash值作为签名,签名随同数据一起发送给浏览器作为cookie,这样后续服务端就可以通过验证签名的方式来判断数据是否被篡改。

其次就是cookie的容量很小只有4kb,而且只能存储一个字符串,存储不了多少信息,最后就是用户其实是可以通过浏览器禁用cookie的,所以我们不能完全依赖cookie保持登录状态。

3.session

所以就有了session,也就是会话。浏览器访问服务端就是会话的开始,比较模糊的是会话的结束的时间,因为你关掉网页也有可能只是点错了而已,因此不同的网站对于用户的会话都设置了时间以及唯一ID,这里的ID就是通常所说的sessionid,这里的时间就是结束会话的时间。因为是服务端自己定义的东西,所以一般都会保存在服务端的数据库。那为什么有了用户名还要有这个sessionid

使用session技术的话,前端发起登录请求,把用户名密码发送给服务器进行验证,如果通过的话,服务端就会保存用户信息比如用户名,会话关闭的时间也就是cookie的有效期,并生成一个key用于数据关联,这个key就是sessionid,这一步和cookie很像。响应给前端的时候会在响应头上添加一个set-cookie的属性,值就是sessionid,前端会自动在cookie中存入当前的sessionid,在后续请求页面的时候就会在请求头上添加cookie,把sessionid给传入到服务端,服务端拿到以后会在保存的用户信息里通过key也就是sessionid找到对应的登录用户信息以维持登录状态,如果超过了有效期就会提示重新登录。

session的使用是非常方便的,请求登录到服务器成功以后存入用户信息时,不仅仅可以存入一个字符串,甚至可以把整个用户信息都存入进去,下次获取的时候是非常方便的。而且安全性高,因为用户信息都是存储在服务端,而且存储的内容也大大增加可以存储整个user对象。

同样session也是有弊端的,因为存储的容量大,在高并发的情况下是会比较占用服务器内存的,而且扩展性比较差以及依然需要依赖cookie这就导致会有跨域问题。

扩展性比较差的意思就是,比如说后端服务器压力比较大,就有可能对它进行集群部署,比如我们前端发起登录请求,服务端往session里存入用户登录信息只会存入到一台服务器,其他的服务器并不会有用户的登录信息。集群之后负载均衡就有可能浏览器的下一次请求就会请求到别的服务器上面,就会判定用户当前未登录。所以在集群的情况下,session是不支持的。

以及现在都是前后端分离的架构方式,在移动互联网盛行的情况下还会有移动端H5,小程序,安卓端,苹果端,他们都会有各自的端口域名,这时候前端再请求后端就会发生跨域,跨域的情况下cookie是默认无法传递的,需要在后端设置允许跨域,还需要在前端单独的设置允许跨域的cookie传递,这是比较麻烦的,所以在集群环境以及前后端分离的架构下session已经不再适用。

session的本质还是cookie,区别就是服务端只给浏览器一个sessionid用于身份区分,用户信息是保存在服务端的。

4.token

前面说了在移动互联网盛行的情况下还会有移动端H5,小程序,安卓端,苹果端,这些客户端的网络请求接口默认是没有cookie机制的,那怎么办呢?客户端程序将sessionid在存储系统里面保存起来,然后sessionid换个名字叫token,这就出来token了。tokensession还是一样的,只是少了浏览器的cookie机制,需要自己维护。客户端为了遵循Bearer认证规范,请求的时候就不再使用Cookie字段(就是前面浏览器发送请求给客户端时请求头自动携带的属性),而是Authorization字段。到这里会发现tokensession的用户数据都是保存在服务端的,在单个服务器下没有问题,如果出现上面所说的集群部署的情况,就会出现某个服务器没有用户数据的情况导致需要重新登录,通常解决这种问题需要服务端再架设一个中心化的存储服务,比如Redis来专门存储用户信息,但是这样也会有问题,如果中心化的服务器出现故障,就会导致所有服务器都连带故障,另外在一些边缘计算平台里也没法使用中心化的服务,所以还是希望用户数据由客户端保管。其实也好办,直接把cookie的数据搬过来作为token就行了,但是前面关于cookie容易被篡改的解决方案是随便想的就会有漏洞,而且对于每个人的算法都不一样(Hash算法),会造成五花八门不方便协作,所有我们就需要一个标准,这个标准就是JWT

JWT全称为json Web token,其实就是通过json来进行传递的加密后的字符串。下面这一段就是通过JWT生成出来的加密以后的token字符串。

它里面由三段信息组成,其中红色部分是header包含了Hash算法token类型(加密类型)。其中算法是不可逆的,所以保证了安全性,将headerjson数据进行base64编码以后就得到了上面的红色信息。

紫色部分是payload负载数据,也就是我们需要传递的数据,这里面存放的就是要存储的信息,比如用户名,用户密码等等用户的信息。通用的这一段json通过base64编码以后就会变成上面的紫色信息。如果我们前端想要获取用户的信息就可以截取紫色信息出来然后通过base64解码,这就可以获取到了。

蓝色部分就是JWT的安全所在了,它是signature,我们称之为密钥,它里面呢会将base64编码后的headerpayload相加,然后再加上只有自己知道的一个私钥,最后再通过header当中指定的算法来进行加密,就得到了蓝色的这一段。

接着来讲一下JWT的使用过程,同样是前端发生登录请求,服务端进行验证,通过以后会创建一个jwt字符串,它会包含三段信息,就是上面那三段信息,然后把创建好的jwt字符串通过响应头的token属性返回给前端,如果前端想要获取到用户的信息,就分割jwt的字符串,前面讲了第二段信息就是保存的用户载体,里面就有用户信息,拿到以后通过base64进行解码即可。登录成功以后后续的请求只需要在请求头当中设置一个跟后端约定的属性,然后再把jwt字符串放进去,后端拿到jwt字符串以后会进行解密,然后会验证这个signature,如果验证成功,信息没有被篡改,就会进行放行,就能保持一个安全的登录状态。

所以使用JWT不需要使用后端的存储,也不需要使用前端的存储,他就是一个加密后的字符串而已,对于现在的集群环境,以及前后端分离的架构,都是可以方便使用的。

token虽然被加密但是其实也是能够被解开的,所以最好不要把敏感信息存入到token里面。

相关推荐
大圣编程26 分钟前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang27 分钟前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆1 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜2 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞3 小时前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农5 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_943782356 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq6 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net
吠品6 小时前
LangChain 里 tool_call_id 为空?一次 MCP 工具集成的排查记录
前端