我目前的理解是.
JWT 在服务器端只需要验证你的 token 是正确的就可以.也就是说数据库里面只需要保存类似这种.
user_id token
然后服务器接到 token 信息,就知道你是谁了.剩下的信息也都在 token 里面装着.不装在服务器端.
要不然我理解不了 JWT 方式和 session 的区别.
1
jswh 2018-10-10 14:26:14 +08:00
session 是存在服务器端的,是服务器端对客户端的访问状态的存储,因为 HTTP 本身是无状态的,但有时候有需要保存状态(比如登录状态),就用这种方式,一般配合 cookie 来使用。token 是访问令牌,就是一种权限的校验机制,JWT 是 token 的一种规范。这里面的概念都不一样,不能这么比。
|
2
rainonline 2018-10-10 14:29:42 +08:00
JWT 是不需要数据库的。当服务器授权生成 Token 之后,用户存储在浏览器中,服务器本身不储存用户的状态。访问服务器时服务器直接算法校验用户传过来的 Token 是否有效。不过这样有一些缺点比如不能服务端设置 Token 无效,只能等他过期。
Session 则是用一个全局变量来存储用户的状态。长期保存需要存储在数据库中,多个服务共享登陆状态时还要做 Session 数据共享等操作,可扩展性差一些但比较容易做控制 |
3
zsh1995 2018-10-10 14:30:58 +08:00
理论上 JWT 的 token 也不需要存数据库吧,验证是基于密码学的签名算法的
|
4
tachikomachann 2018-10-10 14:36:32 +08:00 via Android 1
jwt 也是 session 的一种
传统的 session 验证方式是服务端有存储介质保存用户 session,客户端请求时带上票据来服务端验证。 jwt 基于一套标准的加密方式,加密票据和 session 信息(比如登录用户的数据),并且不需要存储介质就能验证票据合法性,可以做到 session 产生后不需要服务端参与验证。 当然,缺点也很明显,只依赖客户端的话,jwt 无法集中控制用户会话过期,比如后台踢出用户这种操作。 |
5
qq976739120 2018-10-10 14:44:50 +08:00
我现在是登录的时候生成一个 uuid 放到缓存,前端放到 cookie,redis 里 uuid: 用户信息,然后每次访问的时候前端带这个 uuid 过来,缓存里判断是否存在这个 uuid,存在这个 uuid 表示登录. 感觉也蛮方便的
|
6
precisi0nux 2018-10-10 14:46:54 +08:00 via iPhone
@tachikomachann 这也是我一直疑惑的,如果用户改密码了,如何去 invalidate 那个 jwt token。
|
7
mgcnrx11 2018-10-10 14:50:19 +08:00
这个写得挺好的,http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ 。不过不是楼主要的简短的
|
8
sunnysen 2018-10-10 15:19:19 +08:00
明显两个概念 维基一下就知道了 前排别误人子弟
|
9
imn1 2018-10-10 15:26:19 +08:00
session 是一个环境、变量容器,不能把它其中一个用途 /属性抽出来代替它
|
10
crab 2018-10-10 15:30:02 +08:00
@precisi0nux jwt 带上过期时间,过期要重新请求了。
|
11
571726193 2018-10-10 15:40:26 +08:00 1
@rainonline 你好 之前使用过 jwt,但是 道理不是太懂,以下几点能否指点以下:
1,JWT 生成的 token 存放在哪里啊? 2,移动端登录到服务器返回一个 token, 以后每次访问都带着这个 token 来请求接口 ,服务端是通过什么知道 带上来的 token 和 第一次生成的 token 一样的? 菜鸟一枚,真心求教 谢谢大佬 |
12
qwx 2018-10-10 15:51:58 +08:00
@571726193
1、生成的 token 应该传递给客户端存放在客户端 2、我的操作是整个 token 放到 redis,提交上来先验证,当然有大佬告诉我最好不要这么做。 (虽然 token 的验证是通过签名来保证不可伪造就是了) |
14
leafin 2018-10-10 16:08:14 +08:00 1
@571726193 简单理解一下:
在 session 机制下,当用户登录时,服务器从数据库读出用户信息,把用户信息保存在 session 容器里,然后创建一个 sessionId 指向这个用户信息。然后把 sessionId 返回给客户端保存。下次客户端请求时带上 sessionId,服务器查找 sessionId 对应的 session,即可得到用已认证的户信息。 可以理解成服务器创建并保存会员卡,然后把卡号告诉你。你要消费的时候提供卡号就行。 在 JWT 机制下,当用户登录时,服务器从数据库读出用户信息,把用户信息加密生成一个 token。然后把 token 返回给客户端保存。下次客户的请求时带上 token,服务器解密 token,从中得到已认证的用户信息。 可以理解成服务器创建会员卡,然后把卡给你。你要消费的时候要提供会员卡。 |
15
571726193 2018-10-10 16:08:32 +08:00
@leafin 1,JWT 生成的 token 存放在哪里啊?
2,移动端登录到服务器返回一个 token, 以后每次访问都带着这个 token 来请求接口 ,服务端是通过什么知道 带上来的 token 和 第一次生成的 token 一样的? 我想了解的是这两个 , 谢谢 |
16
algery 2018-10-10 16:14:28 +08:00
JWT 无状态; Session 有状态维护
|
17
leafin 2018-10-10 16:31:46 +08:00
|
18
heimeil 2018-10-10 16:40:14 +08:00 1
一个 jwt 是由 3 部分组成,用 . 连接起来 Header.Payload.Signature,主要是最后的签名起到认证的作用,服务端先用 Header 里面的算法对 Payload 进行带密码的签名,别人没密码就签不出来同样的结果,生成后发给客户端,客户端再发给的服务端时,服务端再重复一下之前的签名操作,比对签名是否一致,相同就代表 token 没有被篡改。
就像比较两个 md5 一样,只不过 jwt 是带了密码的,不然谁都可以伪造,签名正确的话 Payload 的内容就是可信的了。 改密码之类强制清理用户 token 问题还需要一个黑名单系统,block 用户一个时间点之前的 token。 |
19
chaleaochexist OP @heimeil 大神,数你说的最简单,而且说得通.
> 改密码之类强制清理用户 token 问题还需要一个黑名单系统,block 用户一个时间点之前的 token。 这个部分就需要用到数据库了对吧? 譬如把过期的或无效的 token 放到数据库里面. |
20
lichao 2018-10-10 16:48:45 +08:00
JWT 不能针对单个用户进行重置?
|
21
heimeil 2018-10-10 17:11:02 +08:00
@chaleaochexist 不用存 token 的,只用存时间点就行了,对应用户 id,最好存在内存或 redis 里,过了你 token 配置的过期时间的那个窗口清理掉就行了,没必要一直存着每次都验证一次,这样资源相对节省一点。
这样其实也不是太科学把,应该还可以探索更好的方法的。 |
22
sobigfish 2018-10-10 17:15:07 +08:00
|
23
xiaoxinshiwo 2018-10-10 17:23:21 +08:00
一个无状态,一个有状态
|
24
mokeychan 2018-10-10 17:34:22 +08:00
我理解 JWT 是一种规范,本身是一种生成 token 的机制。
|
25
ZSeptember 2018-10-10 17:36:57 +08:00
说是两个概念的明显不理解到底是 session。
|
26
leafiy 2018-10-10 18:02:18 +08:00
@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 2018-10-10 18:13:10 +08:00 via iPhone
@crab 这个还是不是 100%靠谱,改密码只是个例子。时间戳没办法保证一改密码就让 token 失效。
|
28
WordTian 2018-10-10 18:16:12 +08:00 via Android
jwt 信息存客户端,session 信息存服务器
|
29
meik2333 2018-10-10 18:18:07 +08:00
对每个用户添加一个额外的参数一起加密解密,服务器端可以修改这个参数来使 token 立即失效。
django 的 jwt 库我记得可以自定义用户的加密解密函数,把加密后的密码一块加入参数就可以保证修改密码 token 立即失效了。 |
30
momocraft 2018-10-10 18:18:52 +08:00
session 是目标(请求关联到实体,多次请求关联到相同实体)
如何传输( cookie 或别的 header,甚至 url 或 body ),内容是什么( key 或实体本身)都是实现细节,包括 JWT |
31
tachikomachann 2018-10-10 18:31:03 +08:00 via Android
@crab jwt 是有过期时间,但是只依赖 client 的 jwt 校验,无法做到让会话提前失效。
|
32
tachikomachann 2018-10-10 18:34:47 +08:00 via Android
@precisi0nux 下面有朋友提到了,就是维护一个失效的 jwt 列表,当然这样就要服务端参与了。
|
33
rainonline 2018-10-10 18:55:44 +08:00
@571726193
1,JWT 生成 Token 的过程通常发生在用户登录的时候。在生成 Token 后随用户请求返回给用户,并储存在用户浏览器的 cookie 中。 2,在 JWT 的规范里,服务器在校验 Token 的时候是不需要进行任何比对的。而仅仅通过算法就能计算出该 Token 是否有效。 |
34
precisi0nux 2018-10-10 21:10:01 +08:00 via iPhone
@tachikomachann 那这不就不是 stateless 了么?
|
35
dorentus 2018-10-10 23:07:01 +08:00 via iPhone
rails 的 session 也可以不存服务器啊,实现细节而已。
|
36
gsw945 2018-10-10 23:52:28 +08:00 2
通常所指的 session,是和 cookie 配对使用的,session 是锁(保存在服务器端),cookie 是钥匙( session-id,存放在客户端,一般是浏览器);客户端发送请求时,查找 session 是否存在(有没有带钥匙?携带的钥匙能否打开锁?)。
而 jwt,类似于一个机关锁,服务器端(可能是分布式,多台服务器)不存储内容,但是记录了开启密码锁的方法;客户端发送请求时,jwt 回传到服务器,尝试用记录的方法去解开机关锁,如果能解开,说明是有效的。 如上 v 友所言,jwt 一般是通过设置过期时间来废弃,但是如果想废弃某一条 token,就需要借助存储手段;但是一般并不是存储完整的 jwt,而是记录 jwt 中的关键信息(比如用户 id ),放入黑名单,就算 jwt 解密成功,但是得到的关键信息在黑名单中,也可以拒绝。 而 session/cookie 方式,session 是存在服务器端的,我把锁销毁了,就算你拿着钥匙来了,找不到能开的锁,也是没用的。 (个人理解,仅供参考) |
37
xiaoshenke 2018-10-11 00:45:03 +08:00 via Android
首先你要知道什么是 session session 解决了什么问题。简单来说 session 就是会话,http 协议是短链接是没有会话的概念的,就是说 http 协议干的事情就是一个请求过来返回一个结果回去。但现实生活中,比如我和你交流,我其实想记一下你是谁,下次我和你说话我就知道是你了,这也是 session 会话的意思。因此 session 是一个场景一个目标,jwt 是完成这件事的其中一个实现。
|
38
cgpiao 2018-10-11 02:42:06 +08:00 via iPhone
你既然数据库里保存 token 了,那 jwt 和 session 还有什么区别。你根本上理解错了 jwt。
|
39
wenzhoou 2018-10-11 07:03:36 +08:00 via Android
补充一下。cookie 是浏览器的默认行为。如果你开发的不是网页,是 app,或者将来有可能开发 app,而不想搞两套的话,那就选 jwt。
|
40
kran 2018-10-11 07:12:11 +08:00 via Android
没人规定 session 存服务器。
|
41
robinlovemaggie 2018-10-11 08:16:59 +08:00 via Android
一个追求效率,一个追求安全。一个面向算法安全,一个面向存储安全。各有优劣,合理取舍。
|
42
Rootrl 2018-10-11 08:53:39 +08:00
|
43
caotian 2018-10-11 09:30:11 +08:00
@precisi0nux 用每个用户的密码作为加密 key 给用户生成 token 如何? 这样用户改了密码之前的 token 全部失效, 会不会有性能问题?
|
44
zhaogaz 2018-10-11 10:39:27 +08:00
区别当然有
session 是会话。它指的是服务端保存的交互状态,就是记录哪些人正在访问我们的网站。java servlet 是通过 jsessionid 的这条 cookie 来追踪的,每次交互的时候,servlet 容器会通过这个 cookie 来识别是哪个 session jwt 全名叫 json web token。一般是每次 http 请求的时候携带的票据,我记得是 oauth 2.0 协议里面的东西。每次 http 请求的时候携带在 header 中。 这两个东西根本就不是并列的,不知道怎么就误会到一起了。其实还挺奇怪的是还有很多人不清楚 cookie 和 session (顺便吐个槽 |
46
dallaslu 2018-10-11 11:14:27 +08:00 1
1. 假期出游,你开车经过检查站,交警拦住了你,检查的驾驶证,性别、年龄、过期时间、防伪标志都没问题,大手一挥,放行了。
2. 离服务站两公里的应急车道上,一个妹子气鼓鼓的踢了几脚她的车子。坐在你副驾上的基友还是单身,给了你一个眼色,你马上把他放下去搭讪。原来妹子的车总是熄火,基友提出帮忙开到服务站。面对妹子不确认的眼神,基友掏出了驾驶证,性别、年龄、过期时间、防伪标志都没问题,妹子果然不再怀疑:果真是个老司机呢! 3. 一路风尘仆仆,你和基友去绿色洗浴城放松。你觉得有点热,喊服务生拿两听可乐,服务生过来看了一眼你的手牌号:777。你基友觉得有点燥热,喊服务生叫两个技师,服务生过来看了一眼他的手牌号:888。结帐时候果然算得分毫不差。 4. 柜台前随手刷了一下朋友圈,一个发小在晒手牌号:绿色洗浴城 666。你跟收银说,666 号的单我买了。收银员说:今天没有 666 号的客人啊,你朋友可能是在其他连锁店里吧。 基友坐在车里发着呆,若有所思。你打趣道:想白天那个妹子呢,还是回味刚才呢?你不会是想着工作的事儿吧? 基友不紧不慢的说:我琢磨着,驾驶证有点像 JWT,过期之前哪都能用,信息都在证上明写着;手牌有点像 SESSION,只能在店里用,消费都记在收银系统里。 你皮笑肉不笑的斜了他一眼,心里骂道:神经病。 |
47
Ravenddd 2018-10-11 11:31:28 +08:00
我认为两个可以一起用, 各司其职
session 控制用户的各个状态都很好, 服务端控制很灵活; JWT 的特点就是无状态偏向与安全认证授权之类的; 之前我也想用 jwt 代替 session, 可是最后发现状态控制如果加上黑名单之类的就变成 session 了, 不知道还有什么应用场景, 知道的大佬请说一下 |
48
wizardoz 2018-10-11 13:05:09 +08:00 1
jwt 是一个认证凭证,从某种意义上说它和 username+password 是对等的。
session_id 是一个会话标识,服务器记录了一次业务的中间状态,当然如果认证状态为“ authenticated ”的话,看起来作用好像和 jwt 一样,但其实不是一样。就算没有用户认证的需要,也可能需要 session 来完成业务。 另:jwt 可以不在服务器上保存任何东西,因为 jwt 是可以用 RSA 签名实现合法性验证。 |
49
caotian 2018-10-11 14:15:50 +08:00
@EchosKK jwt token 不是加密的,里面的 payload 都是明文的, 只是最后一段是 hash 值, 用来判断 token 是否有效。 所以 payload 内容是可以直接读取出来的, 比如如果有 uid 读取出来了, 程序里可以查出来用户密码 hash 什么的, 再进行 jwt hash 判断
|
50
yulitian888 2018-10-11 14:20:44 +08:00
这个问题直接去看 JWT 官网不就好了吗?
简单来说,两者不具备可比性,因为适用场合不同。传统 Web 应用更合适 Session,因为操作是连续的。而 App 等新型网络程序往往需要登录一次管半年,而且是“偶尔”连接,对吧!这就是 JWT 适用场合了呗! |
51
zhzer 2018-10-11 14:28:46 +08:00
简单说 jwt 就是带有前端通信功能(能被前端抓)的 session
jwt 的需求是建立在前后端分离,前后端需要同步用户信息上创建的 由于各种后台框架很繁杂,也就没有特别的 jwt 标准,其实简单修改 session 就能达到 jwt 所需求的效果 |
52
ZhengJL 2018-10-11 14:32:33 +08:00
通俗一点的说 JWT 相当于一把加密后的锁,用户登录服务器把锁给到客户端,客户端每次请求都必须带上,请求到达服务器如果服务器端可以用钥匙解开,并且锁内容没有过期,就说明用户是登录的,如果打不开或者打开后发现过期了,证明登录失效
|