JWT 与“加密 cookie”的应用场景有什么区别?

228 天前
yodhcn  yodhcn

这两种验证策略的应用场景有什么区别?

为什么在刷新有效期上,存储在 cookie 中的 session ,由后端通过中间件在每次请求时都刷新 session 的有效期;而 JWT 通常分为 access_tokenrefresh_token,并由前端通过携带 refresh_token 的请求获取新的 access_token

2758 次点击
所在节点   程序员  程序员
22 条回复
Jiubia
Jiubia
228 天前
我的简单理解是 cookie 用于自己平台使用
JWT 用于给第三方调用
Huelse
Huelse
228 天前
JWT 符合 http 的无状态,可以发到多台服务器一起使用
cookie 更通用但默认只能单台服务器使用,如果需要跨服务器就需要额外的服务来支持
thinkershare
thinkershare
228 天前
JWT 适合: 微服务相互通讯,SSO ,OpenAPI 认证,部分 SPA/Mobile 应用(核心是无状态可以减少每次验证授权的开销)
Session: 传统的前后端耦合的 MVC 引用,安全性高并要求实时销毁授权的,授权信息会快速频繁变化,session 生命期非常短。
重要的是理解 JWT 通过 json 格式(公开 RFC 协议格式), 非对称签名和授权验证端点的组合实现了无状态认证和授权,这种方式在高频的服务相互调用时,可以节省每次都执行完整的重新认证&授权流程的性能开销。
chendy
chendy
228 天前
不懂 laravel ,但是
session 机制其实类似一种 key-value 结构,session 是 value ,key 由服务端生成给到客户端,客户端请求的时候带着 key ,服务端用这个 key 去找到 session
于是主要的点有这么几个:value 存哪里,key 存哪里,key 怎么传递
1. value 存哪里:分服务器端和客户端,服务器端分内存和持久化(进程内进程外),客户端主要就是 jwt
2. key 存哪里:浏览器的话要么很自然的 cookie ,要么 sessionstorage 之类,其他地方各有各的说法
3. key 怎么传,浏览器的话还是要么很自然的 cookie (但是相对的,可能对带来额带宽占用),要么自己塞 header ,其他地方还是各有各的说法

换个角度,常规 key-value 的,key 通常就是一个不容易重复的字符串,而 jwt 属于 key-value 一体,好处是好做无状态,坏处是 key 太大而且无状态


于是:
jwt 机制属于 key 和 value 一体存在客户端,请求的时候自己往 header 里塞的类型(当然放 cookie 里也行但是有点大),因为无状态且有点大,更适合内部服务间通信
而”加密 cookie“应该是最传统的,http 服务自带的 sesion 放内存,session-key 放 cookie 的模式,更加朴实无华适用范围更大
GeekGao
GeekGao
228 天前
JWT 更适合于:需要跨域访问控制或者无状态服务间通信的情况,它提供了一个自包含的、易于验证的令牌。
加密 Cookie 更适合于:需要在客户端存储敏感信息或者管理会话的场景,它通过加密来增强数据的安全性。

一句话总结:它们并不总是相互替代的方案。
gam2046
gam2046
228 天前
该说不说,每周至少看到一次。

https://www.google.com/search?q=site:v2ex.com/t%20jwt%20cookie
yodhcn
yodhcn
228 天前
@chendy 不,laravel 文档里指的是 value 也存储在 cookie 的情况,这样同是无状态,那么这与 jwt 的使用场景有啥不同呢?
zzzzzzggggggg
zzzzzzggggggg
228 天前
@gam2046 点开这个链接,第一个帖子就是我发的😸
wunonglin
wunonglin
228 天前
月经贴。站里搜一下就行了
ExplodingFKL
ExplodingFKL
228 天前
JWT 和 Cookies 区别和优劣

使用 Google 搜索 或者 V2EX 搜索历史帖子 ❌
发新帖骗 v 友银币 ✔
yodhcn
yodhcn
228 天前
@ExplodingFKL #10 你再仔细看看正文,我了解 cookie 、session 、jwt 的区别,但是像 laravel 这种把 session 存 cookie 里的操作不奇怪吗?
mgcnrx11
mgcnrx11
228 天前
在很久很久以前的互联网上,前后端还是不分离的。浏览器显示的网页,都是通过后端的模版技术动态渲染成 HTML ,返回给浏览器的。那时候还没有 Ajax 的流行,浏览器要做的操作,都得一次一次的请求后端,后端返回一个完整的 HTML 页面来显示结果。

在这个背景之下,HTTP 协议又不支持保持会话。那后端怎么知道多个请求之间的联系?例如某个用户先执行操作 A ,然后执行了 B 。所以,需要一种“保持用户状态”的机制,在后端能保存用户的状态使得后端知道用户执行了哪些操作,又能为这些操作保存一些信息。这个就是 Session 会话了。本质上,它是设计出来“保持用户状态”的。

后来,Ajax 使得异步刷新页面,以及后来大前端的流行,各自新的标准和浏览器技术涌现出来。使得我们有更多的方法来做到类似“保持用户状态”的效果。例如,我们可以把用户的状态保存在浏览器端的 Storage 里面。这时候,就会显得后端 Session 来保持用户状态,没有以前那么必要了。当然,也有很多场景会需要在后端保持用户状态。

那么,在不怎么需要后端 Session 来保持用户状态的场景,后端就不需要为用户专门开辟一个区域来存储,它只需要去知道这个请求是否合法的访问就足够了。所以,开始使用了 token 。

所以,session 会在每次访问后,重新刷新 session 的有效期。因为他需要持续保持会话,只要用户一天不离开,会话都需要继续持续下去。某种程度来说,这个有效期时间也可以当成是某个“用户状态”的数据。

另一方面,在使用 token 时,它仅用于判断请求是否合法访问,没有说要用来保持用户状态的。那就很自然的不会去保持用户状态。所以就是一种固定的有效期。不会像会话的场景一样自动延长。也就是只能手动的通过 refresh_token 来延长。

上面说了这么多,都没有提到 cookie 。我理解的是,用不用 cookie 其实都不影响理解 session 和 token 的一些区别。我不能把 token 放在 cookie 吗?我不能把 sessionid 放在 header 用吗?只是没有这个用的习惯而已。
yodhcn
228 天前
@mgcnrx11 #12

我理解你的意思了。

token 中的 payload 只用于鉴权,而 session 中的 payload 可以用于鉴权(将“过期时间”视为一种用户状态),还可以存储一些其它的上下文;而为了保持会话,后端需要在用户活跃期间不断刷新“过期时间”。

session 可以存储用户状态,存储在服务端的 session 可以在让同一用户在不同设备上同步状态,并且不用每次请求都携带用户状态相关的全部参数,只需携带 sessionId 。

从这个角度来看,像 laravel 这种存储在客户端的 session 是不是没有多大意义?既不能在多设备上同步状态,又没必要每个请求都携带用户状态的全部参数,只在必要的 api 里提交必要的参数就可以了。除非,是有希望作为请求参数提交,但又不想在客户端被解读的“用户状态”?这种有类似的场景?
EmbraceQWQ
228 天前
那如果我把 jwt 的 token 加点特色然后放进 cookie 里面呢?
aragakiyuii
228 天前
anonydmer
228 天前
没几个人理解楼主的问题。。。

把 session 加密存在 cookie 中的目的是实现 SNA 架构( shared nothing architecture ),这样服务器端部署的时候可以方便的做多副本部署,因为 session 不存储在每个副本的节点中,也不存在某个统一的集中式存储(例如 redis 或者数据库),不用去处理传统的 session sticky 和 session 复制的问题。 每次服务器接收到一个请求时,是从 cookie 中解密得到 session 值,这样前后两次请求是哪台服务器处理的就不重要了; laravel 我不知道,但是 Rails 在很久以前就这么干了。

之所以要加密是因为两方面的原因,一方面是要防止客户端篡改数据,另一方面是 session 这个设计中是可以存一些敏感数据的。 有人认为加密这个方式可能存在客户端破解的风险,但是实际来看没啥问题(这点 Rails 的文档中有说明过)。
jwt 的设计初衷不同,jwt 中的 payload 对客户端是透明的,所以 jwt 一般不在里面存敏感数据;当然 jwt 也采用了签名验证的机制来防止篡改。

至于刷新时间问题,jwt 因为设计的默认是无状态的机制,一旦签发了就不可撤销,它的生命周期不受服务器控制,所以为了避免泄露后被复用,就让 access token 尽可能短(一般几分钟),而 refresh token 就相对时间长一些,但是它智能用来获取 access token ,不能干别的。 而加密的 session 因为不存在一个服务器端状态来维护它的时间有效性,只好每次使用的时候刷新一下。

@yodhcn
whileFalse
228 天前
JWT:分布式验证,无法直接吊销,所以通过短有效期+频繁刷新实现。
Session:集中式验证(一定要链接 redis 等缓存)可吊销,可实时更新

前者当你在第三方或者客户端直接验证的时候使用。如果你不知道自己在干什么,用 session 。
ragnaroks
228 天前
stateless-cookie 是最早的 authentication ,cookie-session 才是后来的,因为那时候服务器性能孱弱带宽贵,只传递一个 session-id 然后去内存里面查明文可比每次都加密解密高效得多。

cookie 这套适合做 authentication ,jwt 适合做 authorization 。
ragnaroks
228 天前
楼上都在扯 session 可能是被主题误导了,楼主说的 session 应当是 claim
weirdo
228 天前
不要局限于框架的方法,去看 http 协议和 jwt 标准相关的东西

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1054786

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX