HTTP 协议是一种无状态协议,每次服务端接收到客户端的请求时,都是一个全新且独立请求,这样就无法获取历史请求的记录,为了解决这种机制,让某个域名下的所有网页能够共享某些数据,就引出了cookie和session。
cookie
Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下一次向同一服务器再发起请求时被携带并发送到服务器上,服务器通过读取 Cookie 信息,就可以判断该请求来自哪个客户端以及其他的信息。由于他是存储在客户端的,所以很容易被查看和修改,不是很安全,于是引入了session。
- 客户端发送请求
- 服务端返回响应,并在请求头中添加cookie
- 之后客户端再请求时,携带cookie
- 服务端验证cookie并响应
session
Session是一种在服务器端存储用户状态的机制。与Cookie不同,Session数据存储在服务器上,而不是客户端。
一般情况下cookie和session都是一起使用:
- 客户端发送请求
- 服务端创建一个session,并再返回响应时把sessionid添加到请求头中的cookie中。
- 客户端发送其他请求时,携带cookie,服务端用它包含的sessionid找到session
- 服务端验证session后响应
session 是基于 cookie 实现的,在set_cookie时添加了sessionid(一段没有规律的乱码),所以即使客户端的cookie泄露了也不会被理解,所以就更加安全。
但是,这样又会很占用服务器的资源,但同时有很多人需要验证的时候,需要服务端一个一个根据传过来的sessionid到数据库验证。
如果使用集群部署的话,如果在创建session是在A服务器,但是下一次由于负载均衡可能就到另一台服务器了。
token
Token是一种安全机制,通常用于API的身份验证和访问控制。Token通常是一个加密的字符串,代表用户的身份和权限。
JWT就是token的一种实现方式,并且基本是java web领域的事实标准。JWT全称是JSON Web Token。基本可以看出是使用JSON格式传输token。
JWT
JWT的根本其实就是进行签名,把信息通过一种加密方法(密钥)得到加密过后的签名,把原信息和加密过后的签名一起发送给客户端,当客户端再次访问的时候携带它们,服务端只需要通过自身拥有的密钥验证一下信息是否被篡改。如果客户端发送的信息通过密钥得到的签名与服务端自身保存的签名不一致说明信息被篡改了。
JWT实际上就是一段经过base64编码(非加密)过后的字符串,由三部分组成:
- 头部(Header):包含了签名算法和类型,用于指定如何对有效载荷进行编码和签名
- 载荷(Payload):包含了用户的身份信息和其他自定义数据
- 签名(Signature):是对标头和有效载荷进行签名后得到的值,用于验证token的完整性和真实性
把Header.Payload通过一种密钥加密后生成签名,签名在经过base64编码生成的Signature。将三者用点号相连并返回给客户端,密钥永远不会传递给客户端,密钥只保存在服务端。客户端在访问时携带JWT,JWT包含的这三部分,可以通过密钥判断信息是否被篡改和伪造。
其实你会发现JWT整个过程中不涉及加密,不过就是经过了base64编码,可以被轻松的解码,所以其实整个过程就是明文传输,在使用JET的时候不应该传输密码这样的重要的信息。
- 客户端发送登录请求
- 服务端生成Token,包含用户的信息,返回响应时将Token作为相应的一部分
- 当用户再次访问时,在请求
Authorization
头部中包含这个Token - 服务器验证Token并响应
比较
Cookie | Session | Token | |
---|---|---|---|
存储位置 | 客户端 | 服务器端 | 客户端 |
生命周期 | 根据设置,可长可短 | 通常与用户会话相关,会话结束时失效 | 可设置过期时间,过期后需重新认证 |
安全性 | 较低,可被客户端脚本访问 | 较高,数据存储在服务器端 | 依赖于签名和加密算法,但需注意保护密钥 |
传输方式 | 每次HTTP请求自动发送 | 仅在用户登录时创建,后续请求通过Session ID引用 | 每次请求需显式携带 |
性能影响 | 频繁读写可能影响性能 | 服务器端存储大量会话可能影响性能 | 无状态,性能影响较小,但需考虑Token解析和验证 |
跨域支持 | 受同源策略限制 | 通常不支持跨域 | 支持跨域,但需确保安全传输(如使用HTTPS) |
适用场景 | 适合小型会话数据和个性化设置 | 适合需要服务器跟踪用户状态的场景 | 适合无状态应用、API认证和跨域请求 |
防篡改能力 | 较弱,易受XSS和CSRF攻击 | 较强,因为数据不在客户端 | 通过签名算法提供较强的防篡改能力 |
优点 | 跨页面共享信息 - 用户体验好,无需重复登录 | - 信息安全,存储在服务器端 - 适合保持状态 - 适合分布式部署 | - 无状态,适合RESTful API - 跨域请求支持 - 用户信息存储在Token中,减轻服务器压力 - 支持自定义负载和声明 |
缺点 | - 安全性较低,易受攻击(如CSRF、XSS) - 隐私泄露风险 - 可能影响性能,尤其是大量小文件传输 | - 会占用服务器资源 - 分布式部署时存在问题,需要额外机制如Redis共享Session | - 密钥管理复杂,一旦泄露可能导致安全问题 - 过期后需要重新认证,可能导致用户体验下降 - 需要服务器和客户端的配合,配置不当可能导致安全问题 |
若有错误与不足请指出,关注DPT一起进步吧!!!