V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yodhcn
V2EX  ›  程序员

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

  •  
  •   yodhcn ·
    yodhcn · 143 天前 · 2642 次点击
    这是一个创建于 143 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    22 条回复    2024-07-09 13:28:45 +08:00
    Jiubia
        1
    Jiubia  
       143 天前
    我的简单理解是 cookie 用于自己平台使用
    JWT 用于给第三方调用
    Huelse
        2
    Huelse  
       143 天前
    JWT 符合 http 的无状态,可以发到多台服务器一起使用
    cookie 更通用但默认只能单台服务器使用,如果需要跨服务器就需要额外的服务来支持
    thinkershare
        3
    thinkershare  
       143 天前   ❤️ 1
    JWT 适合: 微服务相互通讯,SSO ,OpenAPI 认证,部分 SPA/Mobile 应用(核心是无状态可以减少每次验证授权的开销)
    Session: 传统的前后端耦合的 MVC 引用,安全性高并要求实时销毁授权的,授权信息会快速频繁变化,session 生命期非常短。
    重要的是理解 JWT 通过 json 格式(公开 RFC 协议格式), 非对称签名和授权验证端点的组合实现了无状态认证和授权,这种方式在高频的服务相互调用时,可以节省每次都执行完整的重新认证&授权流程的性能开销。
    chendy
        4
    chendy  
       143 天前
    不懂 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
        5
    GeekGao  
       143 天前
    JWT 更适合于:需要跨域访问控制或者无状态服务间通信的情况,它提供了一个自包含的、易于验证的令牌。
    加密 Cookie 更适合于:需要在客户端存储敏感信息或者管理会话的场景,它通过加密来增强数据的安全性。

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

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

    使用 Google 搜索 或者 V2EX 搜索历史帖子 ❌
    发新帖骗 v 友银币 ✔
    yodhcn
        11
    yodhcn  
    OP
       143 天前
    @ExplodingFKL #10 你再仔细看看正文,我了解 cookie 、session 、jwt 的区别,但是像 laravel 这种把 session 存 cookie 里的操作不奇怪吗?
    mgcnrx11
        12
    mgcnrx11  
       143 天前
    在很久很久以前的互联网上,前后端还是不分离的。浏览器显示的网页,都是通过后端的模版技术动态渲染成 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
        13
    yodhcn  
    OP
       143 天前
    @mgcnrx11 #12

    我理解你的意思了。

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

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

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

    把 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
        17
    whileFalse  
       143 天前
    JWT:分布式验证,无法直接吊销,所以通过短有效期+频繁刷新实现。
    Session:集中式验证(一定要链接 redis 等缓存)可吊销,可实时更新

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

    cookie 这套适合做 authentication ,jwt 适合做 authorization 。
    ragnaroks
        19
    ragnaroks  
       143 天前   ❤️ 1
    楼上都在扯 session 可能是被主题误导了,楼主说的 session 应当是 claim
    weirdo
        20
    weirdo  
       143 天前
    不要局限于框架的方法,去看 http 协议和 jwt 标准相关的东西
    ychost
        21
    ychost  
       143 天前
    其实本质没区别,无非是放 header 的 key 不一样,但是 cookie 有很多安全机制,浏览器可以保障 http_only 前端不能直接获取这个值而 jwt 这个保证不了
    skuuhui
        22
    skuuhui  
       138 天前
    其实没啥本质区别,就是一个加密值在通讯中传递。cookies 也是 http 头。只不过 cookies 有更多的限制情况,jwt 更自由,并且也带来更多不安全因素。如果你很多授权是跨域,跨平台,跨应用的,显然更自由的方式让你开发起来更容易,但不代表其他方式不行,你甚至自定义 token 字段。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2422 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:54 · PVG 23:54 · LAX 07:54 · JFK 10:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.