我个人觉得大量的 web 系统在滥用 jwt token 技术。jwt token 签发后可使用私钥来验证其是否过期和篡改,这个技术用来做下载链接、邮箱验证、或短时间内的一次性验证业务是非常好的。但如果用来做 web 系统的身份认证,那简直糟糕透顶。在真正无状态下,很难平衡签发时间和安全之间的矛盾,还有无法续期导致的用户体验问题。当然,可以打补丁,甚至变得有状态,最后解决以上问题。但是,为什么一开始不用 cookie + session 呢?想听听大家的看法。
#附言 为了更好讨论本主题,下面附加两种会话身份认证的流程,其中前端不限于网页浏览器。
首先感谢@also24《有关 Session 的那些事儿》,文中详细介绍了 Web 会话中的名词和概念,特别是介绍了 Server Side Session 和 Client Side Session 两种模式,
为了探寻究竟,我查询了一下 v2ex 中关于 jwt 的主题贴,发现不少贴子(好资料尽在眼前)。其中最早的帖子甚至可追溯至2014年。遥想当年,大街小巷,大爷大妈都开始用上智能手机了,更别提年轻的小伙子姑娘们,个个手抖的跟筛子似的玩微信摇一摇。那时 3G 网络已全面覆盖,4G 网络建设如火如荼,正是移动互联网风起云涌的时代,移动APP也是趁东风,夜放花千树。正是在这样的背景下,大量年轻程序员加入移动 APP 的开发。其中有位程序员发出以下疑问:
移动 APP 的使用场景登录一次,此后这 APP 打开应该就是已登录。在这种使用场景下,如果会话使用 cookie + session 方案(Server Side Session),最简单的方法就是把 session id 的有效期延长。但简单的把会话有效期延长是不安全的,为了解决这个问题,可以加入 remember me id 实现长期记住登录状态。在短期的 session id 过期后,使用长期 remember me id 重新自动登录。在该主题回复中,有朋友提到,APP 一关闭,储存在 cookie 管理器中的数据自动清空了(待考证)。即使这个问题存在,我估计也是好处理的,只需把 session id 存在别处不清空的地方即可。
如上文中所述,移动APP会话使用cookie + session 方案也是能满足需求的。但是为什么 APP 要用 token 而不用 session 认证?窃以为是以下原因:
时间同样在2014年,vue.js 发布了(同年,HTML5完成标准制定),在此之前,AngularJS 和 React 也已诞生,前端领域开启三足鼎力时代。三年后,有人又问了一个问题:
从问题可看出,提问者认为 JWT 会话方案是先进的,而 cookie + session 会话方案是落后的。曾几何时,cookie + session 会话方案是 WEB 网站的标配,此时正受到 JWT 会话方案的挑战。为什么会出现这种情况,窃以为是受到移动 APP 领域大量采用 JWT 会话方案造成的。在前后端分离模式下,服务端不仅仅给移动APP提供服务,也为网页提供服务。对于这种多端服务,统一会话方案是必然的。这就造成 WEB 网站也出现了使用JWT 会话方案。但为什么会有人觉得JWT方案(Client Side Session)是先进的呢,它究竟有何优势?个人把经得起推敲的优点罗列一二:
当然,对于JWT会话方案,有人在2016年呼吁,请立刻停止使用 JWT 会话。确实,JWT会话方案并非是更为完美,替代cookie + session会话方案的新技术。如在本小标题主题的回复中,不乏有识之士指出,WEB 网站中使用 JWT会话方案存在缺点。那么,对于WEB网站使用 JWT 会话方案有什么缺点呢?如下:
办法总比困难多,其中对于续期问题简单粗暴的办法便是签发一个长效token,安全做法则是加一个长效 refresh token。而对于无法注销但问题,则可以在服务端加入一个黑名单功能。以上做法较为有效的解决了一些 client side session 的缺点,但有些需求仍然无法完美达到,如准确统计实时在线用户、控制账户并发登录数量等。
1
zoharSoul 2021-04-29 16:16:31 +08:00
因为 cookie 不好用啊, 所以要用 token,
既然要生成 token, 与其自己想一套规则, 不如直接用 jwt 的. |
2
leafre 2021-04-29 16:42:57 +08:00
是公钥验签防篡改,refresh_token 可以实现无缝续签,redis 黑名单控制 jwt 失效,安全和有状态之间做取舍。至于 cookie + session,无法满足多端需求
|
3
2kCS5c0b0ITXE5k2 2021-04-29 16:46:26 +08:00
@leafre session 为什么无法满足多端需求
|
4
wshcdr 2021-04-29 16:47:11 +08:00
移动端又没有 session 的
|
5
airplayxcom 2021-04-29 16:48:39 +08:00
那只能说明 你的项目还没有前后分离
|
6
chendy 2021-04-29 16:49:44 +08:00
公司的产品 web 端还是用 cookie 的(其实也可以说是把 token 放在了 cookie 里),没啥问题
客户端和小程序之类的用的自定义的 token 也没用 jwt,因为有大量踢人需求 jwt 太麻烦 |
7
wangxiaoaer 2021-04-29 16:51:42 +08:00
@wshcdr #4 移动端为什么没有 session ?
|
8
hronro 2021-04-29 16:52:55 +08:00 via iPhone 5
JWT token 这个说法看着好难受。JWT 里面的 T 不就是 token 的意思吗,为什么还要在 JWT 后面再加个 token ?
|
9
wshcdr 2021-04-29 16:58:59 +08:00
@wangxiaoaer 手机上的 app,就是没有 session 的
|
10
est 2021-04-29 17:10:48 +08:00
因为一群猴子发现解析 cookie 太难了。格式没有太好的 spec 。就自己用 JSON 糊了一个替代品。
|
11
jorneyr 2021-04-29 17:10:53 +08:00
jwt + 客户端指纹 (IP+浏览器信息...等) 就可以防止滥用的成本
|
13
zoharSoul 2021-04-29 17:28:46 +08:00
@wangxiaoaer #7
先不说 ios, android 上的 cookie 存储你弄过吗? 多域名情况下 cookie 共享弄过吗? 按访问速度动态更换域名的时候 cookie 怎么跟着切? 更换用户登录的时候 cookie 怎么改变? 这时候用 token 不是更方便吗? |
14
wunonglin 2021-04-29 17:44:20 +08:00 1
@zoharSoul #13
后端生成 token(此 token 为自定义的随机字符串,不是 jwt),token data 存 redis 。客户端(web 、ios 、andriod 等),自行存储。请求时带上 token,此时你想带到 header,body,query param 都行呀 这样不就满足服务端控制 token 咯? |
15
keppelfei 2021-04-29 17:44:24 +08:00
存在即合理,市场决定的,移动端的兴起更需要 jwt 的出现。jwt 更多的是一种思想
|
17
aboat365 OP @leafre 感谢指出错误,私钥签发,公钥验证。refresh_token 、redis 黑名单确实能解决问题,但问题是需要前后端写代码去实现,而 cookie+session 方案,几乎不用写什么代码就具备这些功能。对于多端,cookie 存的只是一个 sessionID 字符串,请问支持 http 协议的端带上一个 sessionID 有啥困难,头里加 token 都没问题,带个 sessionID 就不能了?
|
19
aboat365 OP @zoharSoul 这位兄台,其实所谓 cookie+seesion 方案,基本流程是后端生成一个 sessionID,发给前端,前端存起来,后续请求都带上这个 sessionID,实现了有状态的会话跟踪。但迫于种种安全问题,以及浏览器提供的便捷方式,如同域可带上这个 sessionID,跨域不允许; sessionID 返回后浏览器自动将其存储在 cookie 中;但是,以上是对于常规浏览器而言。既然你的是移动端 app 了,这个 sessionID 你想怎么玩就怎么玩,跟 token 使用毫无区别。
|
22
aboat365 OP @wunonglin 有特殊需求无法满足,自定义一套当然 ok,但问题是很多用 jwt 做身份认证的系统,真的是重新造了个轮子,还不圆。
|
24
xuanbg 2021-04-29 19:46:28 +08:00
@leafre 不是不能,而是麻烦。现在都是 RestAPI 的服务端,哪有 session ?搞个 token 多简单,而且也方便搞分布式。
JWT 有他特定的优点,但滥用 JWT 真的不好。既然要有状态了,我自己生成一个 token 很难吗?几行代码的事,能贴合自己的需求,又不用额外引入第三方库。 |
25
zoharSoul 2021-04-29 19:48:30 +08:00
@aboat365 #19 那既然毫无关系, 不就是 token 方案了? 无非是 token 是 jwt 还是自己造轮子, 还是 sessionid,
那么 jwt 比起 sessionid 多携带点信息他不香吗? |
27
FreeEx 2021-04-29 19:55:16 +08:00
因为有 80%的人是跟风用的,根本不了解其中利弊。
|
28
aboat365 OP @zoharSoul 无状态 jwt 对比有状态的 cookie + session,整体代码量自然是前者少,而且看起来简单,但后者是作为标准具有广泛的实现,实际使用几乎不用写什么代码(开发者甚至不需理解其原理,现成的实现也能工作的很好)。而 jwt 即使再简单,前后端也是要写代码的,而且如果无状态 jwt 不能满足你的需求,甚至要写很多代码,所以才说很多使用 jwt 的开发者只是在重新造轮子,还造不圆。 对于 token 中可以多携带信息,这不是什么优点,虽然大家 wifi 千兆,手机都用上 5G 了,但我为啥非得多弄点信息在每次请求中传来传去,jwt 是被迫无奈。
|
29
aboat365 OP @xuanbg 方便分布式还真是 jwt 的优点,每个系统都配置一样的密钥,然后签出去的 token ,大家都能验证。但这个优点,cookie + session 也是有非常成熟的解决方案,一个 session 共享即可。既然业务做得那么大了,都搞分布式了,恐怕无状态的 jwt 方案都不一定能满足需求了。所以,何不用 cookie + session 方案,现成的、成熟的、历经考验的、不用写代码的。
|
30
CODEWEA 2021-04-29 20:34:14 +08:00
1 、为了写简历
2 、前后端分离,前端组件生命周期一体化用 jwt 很方便 |
31
xcstream 2021-04-29 20:55:32 +08:00
为了解决 服务器超过 1000 的话 共享的 redis 压力大吧
|
32
crab 2021-04-29 20:56:31 +08:00
app 因素
|
33
LeeReamond 2021-04-29 21:02:24 +08:00 via Android
你的主题里的 jwt 常规用法根本是错的,可见 lz 没有 jwt 生产部署经验,自然会有疑问。jwt 无状态天生与容器和集群结合,为了附带业务状态,通常用黑名单代替白名单的方式,在高并发数下比 session 方案节约一个数量级以上的资源,你把 jwt 就当成 sessionid 在用,当然会产生为什么要有 jwt 的疑问
|
34
Junzhou 2021-04-29 21:37:23 +08:00 via iPhone 1
@emeab session 做横向扩展比较麻烦,比较依赖于特定服务器。如果多个服务器间共享 session 就更麻烦了
|
35
aboat365 OP @xcstream 没错,无状态 jwt 方案性能更优,但这就变成有状态和无状态会话身份认证的对比了(上千服务器的 web 服务,就不要考虑哪个方案代码多少的问题了,重新造轮子不过是几个程序员几天 996 而已,不费什么力气)。既然讨论有状态无状态,其中必然各有长短,那就看具体需求了,在满足需求的情况下,自然选性能高的方案,毕竟服务器不便宜。
|
36
micean 2021-04-29 22:03:47 +08:00
那得看身份验证是不是中心化的
令牌续期的话,自然也还是 oauth 的那套了 |
37
aboat365 OP @LeeReamond 你看的真准,我真没有 jwt 生产部署经验,甚至没有接触过什么高并发。诚然,无状态比有状态性能更佳,这是因不同方案侧重点不同造成,特别是随着并发量增大,这个差距应该成正比或指数拉大(我真的没有这方面的经验和具体测试数据,如有错,请指正并见谅)。但性能再好,也是要为真实需求而服务。如层主所言,无状态再加黑名单可满足层主系统业务需求,且是高并发服务,相对有状态能减少不少服务器钱的情况下,自然无状态方案佳。但如果只是一些微小服务,为什么那么多也用无状态 jwt 呢?而且发现不少开源软件和技术方案文章,把无状态 jwt 做成了有状态 jwt,这又何解?
|
38
aboat365 OP @Junzhou session 共享在各个 web 服务器中应该都有比较成熟的方案,而且基本不用写代码,所以,比起写代码实现无状态 jwt,这一点都不麻烦。
|
39
LeeReamond 2021-04-29 23:21:02 +08:00
@aboat365 一般合理的框架开发,不是引擎层面的,单纯讨论框架问题,一般都有集成的鉴权方案,因为太过常见,所以合理的解释就是企业各自有集成方案。毕竟部署实际上只需要对接一个分发服务而已,无论多大规模的服务,既然永远不会导致 performance 变差,同时又不需要多写代码,为什么不用呢,如果选 session,即使有万分之一的可能性这个项目做大了,日活上去了,难道到时候再改成可横向扩展的鉴权系统?
|
40
labulaka521 2021-04-29 23:25:50 +08:00
jwt 仔路过,写了一些 web 都是 jwt
|
41
Biluesgakki 2021-04-30 08:54:44 +08:00
讲道理 既然项目都用了 redis 还用 jwt 干啥。。。
|
42
sutra 2021-04-30 08:58:00 +08:00
这个问题我觉得应该分成两部分来讨论,一是服务端验证方案,是 JWT 那样的去中心化存储式的,还是类似 Session ID 那样的中心化存储。然而是和前端的通信协议,是 token 还是 cookie 还是 session……,其实和前端的通信协议没多少可以讨论的,不管是 cookie 还是 session 其本质都是一个字符串那样的 token 。
|
43
siweipancc 2021-04-30 09:01:43 +08:00 via iPhone
看一下分布式下的客户端 ws 链接列表怎么维护吧
|
44
GooGee 2021-04-30 09:14:59 +08:00 1
|
45
CallMeSoul 2021-04-30 09:20:21 +08:00
什么年代了还用 session ?还在写 jsp ? php 和网页混合?前后端分离了解下,多端了解下。
|
46
zzzmh 2021-04-30 09:34:16 +08:00
首先篡改是不现实的,除非你有超算+顶级科学家+无穷的时间
其次如果你服务器要接受超级高并发,就会发现 session 也好,redis 也好,炸内存。分布式是能解但成本捉急。 jwt 是一个折中方案,不是完美方案,但解决 99%的情况没问题,剩下的 1%不管也好,redis 黑名单也好,都不会炸内存了 |
47
aboat365 OP @GooGee #44 这是一篇很棒的文章,较为全面的质疑了 jwt 作为会话系统的优点。但我仍然没有明白,为何大家都在使用 jwt 作会话?
|
48
aboat365 OP @LeeReamond @zzzmh #39 #46 超级高并发,高并发,或未来预期的高并发而选择使用无状态会话来减少服务器压力,这是一个值得进一步探讨的问题。如前回答 #37 所述,无状态性能更优(正比或指数或其它),但作为一个高并发架构,应该有具体的数据来支持。所以,能否分享一下达到何种量级后,无状态性能将显著超越有状态,或者说这将是一个制约系统响应时间的瓶颈。如果有这份数据,将很好的指导架构考量,来决定是否值得缺少有状态的优点,而拥抱无状态。
|
49
aboat365 OP @zzzmh 关于篡改,根据上下文理解你的意思应该是破解 jwt,那确实如你所言,难以破解。但本主题并未说 jwt 容易破解,主题中所说篡改指的是修改了 token ,那么服务器用公钥便能分辨出这是改过的 token,从而实现了防篡改。
|
50
zoharSoul 2021-04-30 10:20:45 +08:00
@aboat365 #28
> 无状态 jwt 对比有状态的 cookie + session,整体代码量自然是前者少,而且看起来简单,但后者是作为标准具有广泛的实现,实际使用几乎不用写什么代码(开发者甚至不需理解其原理,现成的实现也能工作的很好)。 re: 这个你说反了, 移动端上要是用 cookie + session 这套机制要额外写很多代码, 并且复杂很多. |
51
aboat365 OP @zoharSoul #50 我未做过移动端开发,不知道移动端使用 session id 会比使用 token 复杂多少?但请你不要骗我。如果是真的,那这是一个考量点。
|
52
EIJAM 2021-04-30 10:35:29 +08:00 via iPhone
@zoharSoul 移动端把 sessionid 存在 local storage 里面,会用更多代码么?
|
53
a728976009 2021-04-30 10:43:53 +08:00
因为 oauth 和 oidc 几乎已经成为行业的认证标准了,安全有顾虑你可以用 jwe 代替 jwt
|
54
CallMeSoul 2021-04-30 10:44:03 +08:00
@aboat365 cookie + session 是以前时代的标准啊,不是现在的标准啊,现在的标准就是 jwt,而且广泛实现啊,不然也不会这么多人用 jwt,你完全可以自己写个加密协议作为 token 的,就是用了 jwt 这么个标准,而且也是广泛认可的,才这么多人用。不管你承不承认,cookie+seesion 是逐渐淘汰了,jsp 你当我没说。
|
55
zoharSoul 2021-04-30 10:51:34 +08:00
@EIJAM #52 首先, 移动端就没有 local storage . 其次, 既然你要手动存, 那存 sessionid 和存 token 的成本是一样的,
也就不存在楼主说的 sessionid 不需要手动处理. |
56
zoharSoul 2021-04-30 10:53:04 +08:00
@aboat365 #51 你可以自己试一下啊, 麻烦的点我已经说过了,
两个情况: 1. 你想用 cookie 来保存, 这种情况下非常复杂, 尤其涉及多域名切换, 和 h5 共享登录状态等等. 2. 如果你拿着 sessionid 当 token 存, 那这种情况下, 没有任何优势, 成本是一样的.都是手动处理. |
57
chhpt 2021-04-30 10:55:47 +08:00
JWT 和 Cookie 、Session 不是对立的关系,实际上往往是结合使用的。登录鉴权本质上是客户端需要有一个服务端认可的身份标识,而 Session ID 和 JWT 都是这样的身份标识字符,本质上来说区别不大,Cookie 也只是一种保存身份标识的手段。如果在签发 JWT 时加入身份信息,验证 JWT 后再验证身份信息,就变成了有状态的 JWT,就和 Session 没有区别了。
JWT 本质上是一种加密算法,仅此而已,而使用 JWT 的原因大概只是因为它是一种通用规范,支持较好。 |
58
kahlkn 2021-04-30 11:01:47 +08:00 1
如果 jwt 真的那么好,那么你们会发现 各种开放平台,比如 微信三方登陆,阿里云的各种接口等应该都走 jwt 才对。 然而并没有,他们的 appSecret 也好 accessKeySecret 也好,没有一个走 JWT 的。 他们的量级够大把,他们的开发团队够强把,如果这个机制( JWT 的思路,毕竟大厂,也许会自己造轮子)真的好用,他们应该会用上才对。
看看微信的 三方登陆,拿 appId 和 appSecret 去换 access_token (类 UUID 的字符串,其他参数不管)。然后其他接口比如 获取用户的信息的接口,是需要传入 access_token 的(这不就是类似于 session id 的机制嘛)。 人家大厂还在用类似于 session id 那套,等哪天各种 各类的技术博客啥的(比如 美团技术团队 那个博客,还有一些大佬的博客)都强推 JWT 了,再考虑 JWT 把。 |
59
HashV2 2021-04-30 11:02:07 +08:00
我也不想用 领导要求的
|
60
a728976009 2021-04-30 11:05:33 +08:00 1
另外用 session cookie 做单点登录就十分恶心,大型的分布式架构上体验不佳。
认证协议的发展是一个过程,从 session cookie -> saml -> oauth -> oidc,到现在流行的 idaas 服务,每一步发展都是有原因的,你不能倒退着来。 当然这也不是说 session cookie 就无用武之地,session cookie 还有很多使用场景的。 另外 jwt 是分为 jws 和 jwe 的,我们通常指的都是 jws,应该把它看成是一个 encode 方式,jwe 才是 encryption,但这些都不能和认证协议等价。 |
61
a728976009 2021-04-30 11:16:02 +08:00
@kahlkn #58 阿里云有 oidc 服务的 https://oauth.aliyun.com/.well-known/openid-configuration,Google 更是用了 oidc 很久了,甚至还有一个 playground https://developers.google.com/identity/protocols/oauth2/openid-connect
|
62
kahlkn 2021-04-30 11:19:29 +08:00
我们的 分布式 应用场景,就是由 认证授权模块 统一生成一个 类 UUID 的 token,用户登陆成功后,返回给前端,反正前端看着保存呗,别弄丢就行了。 然后每次请求的请求头 都会带有 这个 token,至于多域名跨域问题? 后端配置哪些域名可以进来就好了。
流量 -> 阿里云 LBS -> 业务服务器 Nginx -> 网关 (校验 类 UUID 的 token 是否合法,是否有访问这个接口的权限)-> 业务模块 (获取用户信息工具 根据 token 获取用户信息,并存入 threadlocal ) 如果用户信息存入字段,仅仅存入比如用户昵称几个字段,业务上不一定用得到,还得去查一次,如果都存,一些业务的用户信息敏感不敏感先不说,单纯数据量,就很多,上面的 获取用户信息我们设计的也是分段获取,即你要一个用户属性,会自动拉去一定的用户信息到 threadlocal 中,不全部拉去因为多,也不能保证都用到。 是,jwt 是减少了 网关层面的 一次查询,也仅仅是 token 合法性校验的查询 省去了,但是 接口权限 校验还是要查的把。后面业务模块中获取用户信息大概率还是要再查一次的把。所以呢,JWT 最后还是变成了一个 类 session id 的东西。 至于水平扩展,网关受不了了,加机器。业务模块受不了了,加机器。注册中心大概率不会受不了的。 想怎么加就怎么加,只要有钱就行。 |
63
lldld 2021-04-30 11:19:37 +08:00
因为 jwt 省钱, 省事.
1) sessionId 的有效验证必须依赖后端查询, jwt 是通过计算来验证, 成本低, 速度快. 2) jwt 可以添加一些不敏感的数据, 前后端都可以使用, 减少了查询, 成本低. sessionId 更安全, 但是有多少数据需要这么安全呢? 而且需要高安全性的数据和操作可以要求用户提供其他凭证的, 比如支付时提供密码之类. |
64
liuky 2021-04-30 11:20:57 +08:00
最恶心 session, 相比于把 jwt 变成有状态, session 的滥用才是真真让人感觉到恶心的
|
65
also24 2021-04-30 11:24:31 +08:00 4
@GooGee
这篇文章,还有楼主的附言,实际上在对比都不是 JWT 和 session,而是 Client Side Session 和 Sever Side Session,各种所谓的优势劣势,也是这两种形式的 Session 的差异。 而 JWT 在这个场景下,只是作为 Client Side Session 的具体实现和载体而已。 我在之前的帖子里专门说了这件事,比较冗长,但还是建议看一下: https://www.v2ex.com/t/656457 关于 Session 与 JWT 经常被拿来做对比这件事,也专门做了说明: https://blog.by24.cn/archives/about-session.html#cl-48 |
66
SjwNo1 2021-04-30 11:25:59 +08:00
@a728976009 jwt 有方法可以无状态地实现单点登录吗
|
67
h82258652 2021-04-30 11:26:12 +08:00
看需求看场景呗。session id 也是能存数据库的。jwt 性能高,对移动端友好,但做回收不好弄,得像上面说的弄 redis 黑名单之类的方案,就有额外的工程量。
|
68
a728976009 2021-04-30 11:30:53 +08:00
@SjwNo1 #66 jwt 不是用来解决 sso 的,它是一种 encode 方式,你需要找的是 oidc,建议搜一下关键字 oidc sso
|
69
Slin 2021-04-30 11:32:30 +08:00
@kahlkn 楼主说的 session + cookie 和 JWT 的问题,前面这种方式基本都被淘汰了,JWT 的缺点很明显,其实大部分用 JWT 都没有用无状态特性,只是用来生成一个 token 里面携带了多一些的信息 并没什么不妥。
|
71
falcon05 2021-04-30 11:51:28 +08:00 via iPhone
无状态的 jwt 有很多需求无法满足,比如 revoke,有状态的 jwt 又不如 session 成熟
|
72
kahlkn 2021-04-30 11:53:50 +08:00
首先 阿里云 确实有 JWT 的应用,这个让我确实很高兴,毕竟终于见到 JWT 的大厂的应用场景了。就是 @a728976009 说的 oidc 。 https://helpcdn.aliyun.com/document_detail/93698.html
然后 了解了一下 oidc,感觉 OIDC 和 OAuth 的不同,就是 用 JWT (这里的 JWT 指这种机制,毕竟不同的签名 /加密名称不同) 来做了 用户基础信息 的载体(比如 用户 ID 用户名称),用户的其他信息 还是需要 调用接口去取的。然后因为 OIDC/OAuth 都是用来授权,或者三方登陆的,没有普通业务场景那么多问题,直接 JWT 传过去来获取用户信息就好了。 优势,原来 OAuth 需要 先获取到 access_token ,再去调用 接口 获取用户信息。 而 OIDC 直接 返回了 id_token ( JWT ) 和 access_token (可有可无看服务商),对于大部分 只需要 三方的用户 ID 和 用户昵称的 场景,这样一步就够用了。 至于用 JWT 去获取用户信息这个场景,本来服务于三方授权这样一种业务,你不可能说为 access_token 之类的 还设计什么角色、权限、接口权限 之类的 rbac 那套玩意,毕竟三方授权对于调用者来说我仅仅需要该用户在你网站上的部分用户数据。所以 JWT 的方式其实相对来说 优于 类 session id 模式。 而且那些把 JWT 用来业务系统中的一些问题,比如基本上都不会出现。 |
73
aboat365 OP @also24 拜读了你的文章,写的真棒!特别是提出 Client Side Session 和 Sever Side Session,更加精准简洁的描述了本主题中讨论的问题。在文章中,我发现 Sever Side Session 似乎得到更为广泛的支持。但为什么在国内,Client Side Session 模式特别盛行呢(使用如主题附录中 jwt 的实现)?
|
75
wshcdr 2021-04-30 13:40:12 +08:00 1
无论是 session 还是 jwt 其实就是解决一个问题, 服务端怎么去识别连进来的客户端,session 是 pc 时代的产物,现在移动端盛行了,jwt 更适合了
|
76
sherlockwhite 2021-04-30 13:51:55 +08:00
localstorge 是 web 里面的实现吧,到移动端这边,是不支持 cookie 、session 的,因为他不是浏览器,就没有必要非要上 session 。这没什么问题吧
|
77
namelosw 2021-04-30 13:59:51 +08:00 1
我搞过挺多这个,其实我觉得别的因素都是次要的,作为主要原因说不通,主要的因素还是性能 / 横向扩展性。
流量不大的时候我觉得 Session 更简单好用。JWT 实现后续功能的时候基本上都是各种 Hack 。 JWT 流行主要因为 JWT 横向扩展性好,不浪费后端资源。 像 Google 力推 OIDC 这种 SSO 方案思路也类似,目的就是 stateless,这样才比较容易对付亿级的用户。 |
78
baiyi 2021-04-30 14:06:19 +08:00
想起了我几年前的提问帖子......《请教各位一个问题, 为什么 session 机制没有被 JWT 所取代?》
现在 JWT 有了更多的使用场景,其实已经有很大的发展了。 |
79
aboat365 OP |
80
index90 2021-04-30 14:25:18 +08:00
jwt 和 session 的最大区别是去中心化。
现在 web 网站,登录时一个一个站点:account.xxx.com 看视频是一个站点:video.xxx.com 论坛是另一个站点:bbs.xxx.com 如果用 session,那么所有站点都需要对接到一个中心化存储( redis ) 如果是 jwt,只需要验证签名就完事了 |
81
lanlanye 2021-04-30 14:25:58 +08:00
我个人看好 JWT 的原因是它无状态,不需要后端维护 Session,想一下当并发量极高的时候你的 Session 要怎么处理?
|
82
zzl22100048 2021-04-30 14:26:10 +08:00
@kahlkn oidc 是认证协议( authentication protocol ),OAuth2 是授权协议( authorization protocol )
|
83
karloku 2021-04-30 14:28:26 +08:00
jwt 是一套信息传递机制. 并不是一套认证方案. 和 cookie 也不冲突你可以把 jwt 存在 cookie 里用.
不用 cookie 做认证的原因很简单. 后端是 api 的时候用 header 而不是 cookie 对 xsrf 防御更好. 如果用 cookie 还得协调前后端做一套 xsrf-token 来进行防御. 而 header 只需要在 ugc 内容的过滤和呈现上防止 xss 出现就好. |
84
baiyi 2021-04-30 14:39:45 +08:00
@aboat365 #79 是的,现在 JWT 使用场景更多了,但也不能说 JWT 替代了 session,哪怕是 OIDC 中也不是用 JWT 格式作为 accesstoken 。服务端在有相应的场景下,该存的状态还是没少,其实是等同于 session 机制,只不过是原来 session + cookie 被现在的流行的认证格式取代了。
|
85
otakustay 2021-04-30 14:40:45 +08:00
JWT 正是平衡签发和安全后的产物,你所谓的“很难平衡”其实是把安全当作一个无底限的高要求在看吧
|
86
alexkkaa 2021-04-30 14:46:17 +08:00 via Android
这种适合无浏览器环境的场景, 浏览器环境下 cookie 绝对够用
|
87
pkoukk 2021-04-30 15:08:59 +08:00
有 sql 了为啥要有 nosql,有 redis 为啥还有那么多 mq,不是不能实现,而是有的时候用起来更顺手更合适而已。
在“能否达成相同效果”这点上纠结就进入误区了 |
88
kahlkn 2021-04-30 15:13:19 +08:00
@zzl22100048 本质上都是用来做 三方登陆 的,都可以说是属于 认证 把(应该把)?。 OAuth2 第一步是 授权,第二部 根据 access_token 获取用户信息,不就算是 认证 嘛。 oidc 第一步 就返回了 id_token,而 id token 又包含有用户信息,所以称为认证。
|
89
sonxzjw 2021-04-30 15:16:16 +08:00
jwt 确实存在楼主所说的弊端,但不如换个想法来解决如何
随意说一个吧,身份认证应该不是 jwt 的弊端,身份认证是审查有没有你这个人,之后才有鉴权。 所以即使 jwt 过期时间 1 万年也没有影响哒 |
90
woostundy 2021-04-30 15:40:19 +08:00
为了解决 session 到底咋存的问题。
jwt 的答案:客户端自己存,服务端只校验有效性。 |
91
OldCarMan 2021-04-30 15:43:43 +08:00
@chendy 其实可以搞一个黑名单之类(想要踢的人,ip 等等之类的)的有状态缓存(或者持久化),然后每次解析 jwt 时,做一次黑名单的过滤,PS:不知道我有没有理解错你说的踢人。
|
92
trlove 2021-04-30 16:08:28 +08:00
@hronro 哈哈哈 这就是词性问题。jwt 的 T 是 token 不假 但是合起来 jwt 它就代表一个约定,jwt 整体就是一个名词。token 这个机制本身也是一个独立名词。所以合起来也没问题。用生活现象来举例就是公交站牌 假设有 A B站 C三个站点 ,你可以说我到A下了 也可以加个字说我到 A 站下了 同时 你也可以说我到 B 站下 亦或是 B 站站下 …… 只要自己觉得不别扭就行 哈哈哈哈。这个问题的源头在于定义 jwt 的人吧 token 这个常用词 集成到它的约定的命名方式里面去了。
|
93
dorentus 2021-04-30 17:50:25 +08:00
@kahlkn 拿微信和阿里说事没有任何说服力。微信开放平台的 API 里面现在还有 JSON 和 XML 混用的呢,能学吗?
|
94
Owenjia 2021-05-01 09:56:35 +08:00 1
|
95
aboat365 OP @Owenjia 阅读了一下 paseto 官方介绍
https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid 其中罗列了 jwt 、jwe 、jws 的各种安全漏洞,paseto 的设计更为安全,有望替代 jwt 。最后在总结部分说明: Don't use JWT for session management, as discussed in other articles. 请勿使用 JWT 进行会话管理,如其他文章所述。 For secure sessions: Just use cookies over HTTPS. Cookies should only store a random identifier which is paired with a server-side persistent storage mechanism. 对于安全会话:只需通过 HTTPS 使用 cookie 。Cookies 仅应存储与服务器端持久性存储机制配对的随机标识符。 |
96
0xD800 72 天前
个人觉得 jwt 思想适用于后端微服务间的通信使用,这种情况下网关先鉴权然后用 jwtToken 在服务间使用 0.0 这样是不是好一点?
|