想必很多前端同学在面试的时候都被问到过:你知道Cookie和Session的吗?它们有什么区别?
重点是前端,对于前端开发者来说,cookie就是浏览器一个可以存储数据的地方,并且可以通过http请求自动发送给服务器,而作为前端本身来说,基本上很少去操作和管理cookie数据的。
而session,对于前端来说,压根就没有这一个东西。可能大概了解session是服务器端的东西,一般有一个sessionId
放在前端的cookie里面,是后端用于识别用户的唯一标识。
对于前端来说,两个东西都不在一个维度上,而面试官却老是喜欢问他们的区别。
为什么前端会经常被问到?
后来,我自己大概总结了一下,面试官问它们的时候,往往都是指用户登录的场景。他们所谓的cookie,并不是单指浏览器的cookie,而是指基于浏览器的cookie,所实现的用户身份认证的这一场景。
cookie和session都是指这一场景,那么,此时就可以比较他们的区别了。
基于纯cookie的身份认证
为什么要加纯 这个关键字呢?主要是方便理解,因为session通常也是需要借助于cookie来实现。所谓的纯cookie ,就是指服务器将当前登录用户的信息(非敏感信息)直接存储在cookie中(当然,后端也可以对用户相关的信息进行加密处理,避免明文显示)。
后续每次访问后端服务器的时候,浏览器都会自动携带这些用户信息的cookie,后端通过解析cookie信息就能直接识别当前的用户身份。
基于session的身份认证
服务端会在登录之后,将用户相关的信息存储在服务器端(可以是内存,也可以是Redis、数据库),然后对应一个唯一的sessionId。服务端只需要下发sessionId给前端,后续每次访问服务器的时候,只需要将这个sessionId发送给服务器,后端根据这个sessionId就可以去内存或Redis中找到对应的用户信息。
关于这个sessionId,后端通常也会通过cookie来存储,对于前端来说是无感知的。
安全性
从安全性方面来说,看上去session的方式好像更加安全一些,因为它将用户的真实信息存储在了服务器端,只是间接地暴露出去了一个sessionId。但是,如果sessionId是通过cookie下发 ,那么cookie存在的风险理论上session也有,除了无法直接拿到真实用户信息。
比如,常见的XSS攻击、CSRF攻击等,攻击者不需要知道用户的信息,只需要伪造当前用户发送请求就可以了。因此,服务端通常都需要在cookie中设置:
-
HttpOnly:禁止客户端通过js脚本获取cookie内容(防XSS);
-
Secure:只允许通过https协议传输cookie(防止中间人攻击);
-
SameSite:设置 SameSite=Strict/Lax,限制 Cookie 跨站发送(防 CSRF);
另外,如果要规避这些潜在风险,或者在非web应用中,sessionId也可以直接下发(不是用cookie)给客户端,让客户端的在后续请求中手动携带sessionId。
JWT 认证
谈到上面两种认证方案,前端一定也听过JWT,
JWT(Json Web Token)是一种基于JSON的轻量级认证方案,它主要的特点就是无状态认证,即服务端不需要存储用户的状态信息,尤其是对现在分布式应用、前后端分离场景下,使用更加友好。
这玩意与第一种基于cookie认证方式一样,都不需要服务端存储数据。只不过JWT有一套自己的算法逻辑,来保证数据的安全性。它放在浏览器的cookie中,也可以下发给客户端,让客户端自己管理并且通过请求头的Authorization字段发送给服务端。
它如何保证了数据的安全性呢?
JWT的安全性主要体现在防篡改上面,也就是说:只有我自己(服务器)颁发的token,我才认可。
它由三部分组成:header.payload.signature。其中载荷部分包含了用户相关的信息(userId,roleId等),但不能存放敏感信息,因为它只是Base64编码的,并不是真正的加密。最重要的是签名部分,它保证了这个token的真实、有效,如果被篡改过,签名就会不匹配,服务端就不会认可。
它的问题主要在于无法主动失效,只能等token过期。一般有效的解决方案就是缩短过期时间、加入黑名单等。
总结
就Web端来说,个人感觉,cookie和JWT两种认证方案更像,JWT主要在于不可伪造和防篡改,因为签名机制的存在。当然,对于非Web端,cookie根本就不适用了,只能使用JWT方案。
而session主要的问题还是在于信息的存储,对于复杂度较高的应用,增加的管理的难度,也会增加查询性能开销。
至于安全性,可以分为两类,一种是基于cookie,一种是不需要cookie。
基于cookie的,需要考虑cookie相关的安全性问题;不需要cookie的,就需要客户端自己来保证安全性。无论哪一种,都一定要使用HTTPS来传输。因为它直接对传输的数据进行了加密,从根本上增加了数据的安全性。
那么,还有哪些需要补充的?请留下你的观点。