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

谁能用简短的语言解释 JWT 和 session 的区别?

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

    我目前的理解是.

    JWT 在服务器端只需要验证你的 token 是正确的就可以.也就是说数据库里面只需要保存类似这种.

    user_id token

    然后服务器接到 token 信息,就知道你是谁了.剩下的信息也都在 token 里面装着.不装在服务器端.

    要不然我理解不了 JWT 方式和 session 的区别.

    53 回复  |  直到 2018-10-12 00:34:43 +08:00
        1
    jswh   63 天前
    session 是存在服务器端的,是服务器端对客户端的访问状态的存储,因为 HTTP 本身是无状态的,但有时候有需要保存状态(比如登录状态),就用这种方式,一般配合 cookie 来使用。token 是访问令牌,就是一种权限的校验机制,JWT 是 token 的一种规范。这里面的概念都不一样,不能这么比。
        2
    rainonline   63 天前
    JWT 是不需要数据库的。当服务器授权生成 Token 之后,用户存储在浏览器中,服务器本身不储存用户的状态。访问服务器时服务器直接算法校验用户传过来的 Token 是否有效。不过这样有一些缺点比如不能服务端设置 Token 无效,只能等他过期。

    Session 则是用一个全局变量来存储用户的状态。长期保存需要存储在数据库中,多个服务共享登陆状态时还要做 Session 数据共享等操作,可扩展性差一些但比较容易做控制
        3
    zsh1995   63 天前
    理论上 JWT 的 token 也不需要存数据库吧,验证是基于密码学的签名算法的
        4
    tachikomachann   63 天前 via Android   ♥ 1
    jwt 也是 session 的一种
    传统的 session 验证方式是服务端有存储介质保存用户 session,客户端请求时带上票据来服务端验证。
    jwt 基于一套标准的加密方式,加密票据和 session 信息(比如登录用户的数据),并且不需要存储介质就能验证票据合法性,可以做到 session 产生后不需要服务端参与验证。

    当然,缺点也很明显,只依赖客户端的话,jwt 无法集中控制用户会话过期,比如后台踢出用户这种操作。
        5
    qq976739120   63 天前
    我现在是登录的时候生成一个 uuid 放到缓存,前端放到 cookie,redis 里 uuid: 用户信息,然后每次访问的时候前端带这个 uuid 过来,缓存里判断是否存在这个 uuid,存在这个 uuid 表示登录. 感觉也蛮方便的
        6
    precisi0nux   63 天前 via iPhone
    @tachikomachann 这也是我一直疑惑的,如果用户改密码了,如何去 invalidate 那个 jwt token。
        7
    mgcnrx11   63 天前
    这个写得挺好的,http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ 。不过不是楼主要的简短的
        8
    sunnysen   63 天前
    明显两个概念 维基一下就知道了 前排别误人子弟
        9
    imn1   63 天前
    session 是一个环境、变量容器,不能把它其中一个用途 /属性抽出来代替它
        10
    crab   63 天前
    @precisi0nux jwt 带上过期时间,过期要重新请求了。
        11
    571726193   63 天前   ♥ 1
    @rainonline 你好 之前使用过 jwt,但是 道理不是太懂,以下几点能否指点以下:
    1,JWT 生成的 token 存放在哪里啊?
    2,移动端登录到服务器返回一个 token, 以后每次访问都带着这个 token 来请求接口 ,服务端是通过什么知道 带上来的 token 和 第一次生成的 token 一样的?

    菜鸟一枚,真心求教 谢谢大佬
        12
    qwx   63 天前
    @571726193
    1、生成的 token 应该传递给客户端存放在客户端
    2、我的操作是整个 token 放到 redis,提交上来先验证,当然有大佬告诉我最好不要这么做。
    (虽然 token 的验证是通过签名来保证不可伪造就是了)
        13
    leafin   63 天前
    @571726193 简单理解一下:在 session 机制下,当用户登录时,服务器从数据库读出用户信息
        14
    leafin   63 天前   ♥ 1
    @571726193 简单理解一下:
    在 session 机制下,当用户登录时,服务器从数据库读出用户信息,把用户信息保存在 session 容器里,然后创建一个 sessionId 指向这个用户信息。然后把 sessionId 返回给客户端保存。下次客户端请求时带上 sessionId,服务器查找 sessionId 对应的 session,即可得到用已认证的户信息。
    可以理解成服务器创建并保存会员卡,然后把卡号告诉你。你要消费的时候提供卡号就行。

    在 JWT 机制下,当用户登录时,服务器从数据库读出用户信息,把用户信息加密生成一个 token。然后把 token 返回给客户端保存。下次客户的请求时带上 token,服务器解密 token,从中得到已认证的用户信息。
    可以理解成服务器创建会员卡,然后把卡给你。你要消费的时候要提供会员卡。
        15
    571726193   63 天前
    @leafin 1,JWT 生成的 token 存放在哪里啊?
    2,移动端登录到服务器返回一个 token, 以后每次访问都带着这个 token 来请求接口 ,服务端是通过什么知道 带上来的 token 和 第一次生成的 token 一样的?

    我想了解的是这两个 , 谢谢
        16
    algery   63 天前
    JWT 无状态; Session 有状态维护
        17
    leafin   63 天前
    @571726193 我觉得我已经讲清楚了。
    1.token 返回给客户端了,服务器不保存。
    2.没有什么第一个第二个的,服务器收到 token 的时候,能成功解密,就说明用户身份没问题。
        18
    heimeil   63 天前   ♥ 1
    一个 jwt 是由 3 部分组成,用 . 连接起来 Header.Payload.Signature,主要是最后的签名起到认证的作用,服务端先用 Header 里面的算法对 Payload 进行带密码的签名,别人没密码就签不出来同样的结果,生成后发给客户端,客户端再发给的服务端时,服务端再重复一下之前的签名操作,比对签名是否一致,相同就代表 token 没有被篡改。

    就像比较两个 md5 一样,只不过 jwt 是带了密码的,不然谁都可以伪造,签名正确的话 Payload 的内容就是可信的了。

    改密码之类强制清理用户 token 问题还需要一个黑名单系统,block 用户一个时间点之前的 token。
        19
    chaleaochexist   63 天前
    @heimeil 大神,数你说的最简单,而且说得通.

    > 改密码之类强制清理用户 token 问题还需要一个黑名单系统,block 用户一个时间点之前的 token。
    这个部分就需要用到数据库了对吧?
    譬如把过期的或无效的 token 放到数据库里面.
        20
    lichao   63 天前
    JWT 不能针对单个用户进行重置?
        21
    heimeil   63 天前
    @chaleaochexist 不用存 token 的,只用存时间点就行了,对应用户 id,最好存在内存或 redis 里,过了你 token 配置的过期时间的那个窗口清理掉就行了,没必要一直存着每次都验证一次,这样资源相对节省一点。

    这样其实也不是太科学把,应该还可以探索更好的方法的。
        23
    xiaoxinshiwo   63 天前
    一个无状态,一个有状态
        24
    mokeychan   63 天前
    我理解 JWT 是一种规范,本身是一种生成 token 的机制。
        25
    ZSeptember   63 天前
    说是两个概念的明显不理解到底是 session。
        26
    leafiy   63 天前
    @571726193

    1. 客户端 token 存在 localstorage 或者 cookies 随意

    2. jwt token 本身包含过期时间和认证信息和用户 ID,服务端验证时需要解密,解密通过就是已登录用户,不通过就是未登录,逻辑非常简单

    !永!远!不!要!在服务端存储任何 token,包括 redis,真的!没!有!必!要!
    除非解码加密运算影响到你服务器性能了

    一个最简单的 express 的例子,客户端通过 headers 或其他各种方式,每次访问时都携带,服务端接收后解一下
    secrets 是定好的,不要泄露

    let decoded = jwt.verify(token, secrets);
    // decoded 失败直接 401 啊

    let userId = decoded.id;
    let exp = decoded.exp;
    // token 过期了
    if (exp < now) {
    return res.status(401).send({ reason: 'tokenExpired' });
    }
    // 验证 userId 是不是存在
    省略*****

    // 生成新的 token 发回去
    签发新的 token ****
    res.status(200).send({
    token: newToken
    })

    或者用 expressJwt 直接集成到 router 中

    expressJwt({ secret: secrets, credentialsRequired: true })
        27
    precisi0nux   63 天前 via iPhone
    @crab 这个还是不是 100%靠谱,改密码只是个例子。时间戳没办法保证一改密码就让 token 失效。
        28
    WordTian   63 天前 via Android
    jwt 信息存客户端,session 信息存服务器
        29
    meik2333   63 天前
    对每个用户添加一个额外的参数一起加密解密,服务器端可以修改这个参数来使 token 立即失效。

    django 的 jwt 库我记得可以自定义用户的加密解密函数,把加密后的密码一块加入参数就可以保证修改密码 token 立即失效了。
        30
    momocraft   63 天前
    session 是目标(请求关联到实体,多次请求关联到相同实体)

    如何传输( cookie 或别的 header,甚至 url 或 body ),内容是什么( key 或实体本身)都是实现细节,包括 JWT
        31
    tachikomachann   63 天前 via Android
    @crab jwt 是有过期时间,但是只依赖 client 的 jwt 校验,无法做到让会话提前失效。
        32
    tachikomachann   63 天前 via Android
    @precisi0nux 下面有朋友提到了,就是维护一个失效的 jwt 列表,当然这样就要服务端参与了。
        33
    rainonline   63 天前
    @571726193
    1,JWT 生成 Token 的过程通常发生在用户登录的时候。在生成 Token 后随用户请求返回给用户,并储存在用户浏览器的 cookie 中。
    2,在 JWT 的规范里,服务器在校验 Token 的时候是不需要进行任何比对的。而仅仅通过算法就能计算出该 Token 是否有效。
        34
    precisi0nux   63 天前 via iPhone
    @tachikomachann 那这不就不是 stateless 了么?
        35
    dorentus   63 天前 via iPhone
    rails 的 session 也可以不存服务器啊,实现细节而已。
        36
    gsw945   63 天前   ♥ 2
    通常所指的 session,是和 cookie 配对使用的,session 是锁(保存在服务器端),cookie 是钥匙( session-id,存放在客户端,一般是浏览器);客户端发送请求时,查找 session 是否存在(有没有带钥匙?携带的钥匙能否打开锁?)。

    而 jwt,类似于一个机关锁,服务器端(可能是分布式,多台服务器)不存储内容,但是记录了开启密码锁的方法;客户端发送请求时,jwt 回传到服务器,尝试用记录的方法去解开机关锁,如果能解开,说明是有效的。

    如上 v 友所言,jwt 一般是通过设置过期时间来废弃,但是如果想废弃某一条 token,就需要借助存储手段;但是一般并不是存储完整的 jwt,而是记录 jwt 中的关键信息(比如用户 id ),放入黑名单,就算 jwt 解密成功,但是得到的关键信息在黑名单中,也可以拒绝。

    而 session/cookie 方式,session 是存在服务器端的,我把锁销毁了,就算你拿着钥匙来了,找不到能开的锁,也是没用的。
    (个人理解,仅供参考)
        37
    xiaoshenke   63 天前 via Android
    首先你要知道什么是 session session 解决了什么问题。简单来说 session 就是会话,http 协议是短链接是没有会话的概念的,就是说 http 协议干的事情就是一个请求过来返回一个结果回去。但现实生活中,比如我和你交流,我其实想记一下你是谁,下次我和你说话我就知道是你了,这也是 session 会话的意思。因此 session 是一个场景一个目标,jwt 是完成这件事的其中一个实现。
        38
    cgpiao   63 天前 via iPhone
    你既然数据库里保存 token 了,那 jwt 和 session 还有什么区别。你根本上理解错了 jwt。
        39
    wenzhoou   63 天前 via Android
    补充一下。cookie 是浏览器的默认行为。如果你开发的不是网页,是 app,或者将来有可能开发 app,而不想搞两套的话,那就选 jwt。
        40
    kran   63 天前 via Android
    没人规定 session 存服务器。
        41
    robinlovemaggie   63 天前 via Android
    一个追求效率,一个追求安全。一个面向算法安全,一个面向存储安全。各有优劣,合理取舍。
        43
    caotian   63 天前
    @precisi0nux 用每个用户的密码作为加密 key 给用户生成 token 如何? 这样用户改了密码之前的 token 全部失效, 会不会有性能问题?
        44
    zhaogaz   62 天前
    区别当然有

    session 是会话。它指的是服务端保存的交互状态,就是记录哪些人正在访问我们的网站。java servlet 是通过 jsessionid 的这条 cookie 来追踪的,每次交互的时候,servlet 容器会通过这个 cookie 来识别是哪个 session

    jwt 全名叫 json web token。一般是每次 http 请求的时候携带的票据,我记得是 oauth 2.0 协议里面的东西。每次 http 请求的时候携带在 header 中。

    这两个东西根本就不是并列的,不知道怎么就误会到一起了。其实还挺奇怪的是还有很多人不清楚 cookie 和 session (顺便吐个槽
        45
    EchosKK   62 天前
    @caotian 我刚也想到这个,但是会有个问题,解密的时候,用户密码从哪儿来?
        46
    dallaslu   62 天前   ♥ 1
    1. 假期出游,你开车经过检查站,交警拦住了你,检查的驾驶证,性别、年龄、过期时间、防伪标志都没问题,大手一挥,放行了。

    2. 离服务站两公里的应急车道上,一个妹子气鼓鼓的踢了几脚她的车子。坐在你副驾上的基友还是单身,给了你一个眼色,你马上把他放下去搭讪。原来妹子的车总是熄火,基友提出帮忙开到服务站。面对妹子不确认的眼神,基友掏出了驾驶证,性别、年龄、过期时间、防伪标志都没问题,妹子果然不再怀疑:果真是个老司机呢!

    3. 一路风尘仆仆,你和基友去绿色洗浴城放松。你觉得有点热,喊服务生拿两听可乐,服务生过来看了一眼你的手牌号:777。你基友觉得有点燥热,喊服务生叫两个技师,服务生过来看了一眼他的手牌号:888。结帐时候果然算得分毫不差。

    4. 柜台前随手刷了一下朋友圈,一个发小在晒手牌号:绿色洗浴城 666。你跟收银说,666 号的单我买了。收银员说:今天没有 666 号的客人啊,你朋友可能是在其他连锁店里吧。

    基友坐在车里发着呆,若有所思。你打趣道:想白天那个妹子呢,还是回味刚才呢?你不会是想着工作的事儿吧?

    基友不紧不慢的说:我琢磨着,驾驶证有点像 JWT,过期之前哪都能用,信息都在证上明写着;手牌有点像 SESSION,只能在店里用,消费都记在收银系统里。

    你皮笑肉不笑的斜了他一眼,心里骂道:神经病。
        47
    Ravenddd   62 天前
    我认为两个可以一起用, 各司其职
    session 控制用户的各个状态都很好, 服务端控制很灵活;
    JWT 的特点就是无状态偏向与安全认证授权之类的;

    之前我也想用 jwt 代替 session, 可是最后发现状态控制如果加上黑名单之类的就变成 session 了, 不知道还有什么应用场景, 知道的大佬请说一下
        48
    wizardoz   62 天前   ♥ 1
    jwt 是一个认证凭证,从某种意义上说它和 username+password 是对等的。
    session_id 是一个会话标识,服务器记录了一次业务的中间状态,当然如果认证状态为“ authenticated ”的话,看起来作用好像和 jwt 一样,但其实不是一样。就算没有用户认证的需要,也可能需要 session 来完成业务。

    另:jwt 可以不在服务器上保存任何东西,因为 jwt 是可以用 RSA 签名实现合法性验证。
        49
    caotian   62 天前
    @EchosKK jwt token 不是加密的,里面的 payload 都是明文的, 只是最后一段是 hash 值, 用来判断 token 是否有效。 所以 payload 内容是可以直接读取出来的, 比如如果有 uid 读取出来了, 程序里可以查出来用户密码 hash 什么的, 再进行 jwt hash 判断
        50
    yulitian888   62 天前
    这个问题直接去看 JWT 官网不就好了吗?

    简单来说,两者不具备可比性,因为适用场合不同。传统 Web 应用更合适 Session,因为操作是连续的。而 App 等新型网络程序往往需要登录一次管半年,而且是“偶尔”连接,对吧!这就是 JWT 适用场合了呗!
        51
    zhzer   62 天前
    简单说 jwt 就是带有前端通信功能(能被前端抓)的 session

    jwt 的需求是建立在前后端分离,前后端需要同步用户信息上创建的
    由于各种后台框架很繁杂,也就没有特别的 jwt 标准,其实简单修改 session 就能达到 jwt 所需求的效果
        52
    ZhengJL   62 天前
    通俗一点的说 JWT 相当于一把加密后的锁,用户登录服务器把锁给到客户端,客户端每次请求都必须带上,请求到达服务器如果服务器端可以用钥匙解开,并且锁内容没有过期,就说明用户是登录的,如果打不开或者打开后发现过期了,证明登录失效
        53
    qile11   62 天前 via Android
    @ZhengJL
    同意一些,jwt 应该是为了保证客户端与服务器通讯安全而产生的,过期时间和密码是保证安全的方式,可以不设置过期时间,解密后可以通过用户名验证用户的合法性,也可以将一些数据加密传输(有些接口会使用 jwt 加密传输接口数据)。
    session 应该是一种服务器应用,保持回话并存储一些数据,一般保存与服务器,cookie 保存与客户端。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3718 人在线   最高记录 4019   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 25ms · UTC 02:28 · PVG 10:28 · LAX 18:28 · JFK 21:28
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1