GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>电脑问题 > 你管这破玩意儿叫 Token?

你管这破玩意儿叫 Token?

来源:Ghost系统之家浏览:时间:2023-08-25 09:00:48

上周我们在团队内部首次采用了 jwt(Json Web Token) token 这种 no-session的方式来作用户的账号验证,发现网上很多文章对token 的介绍有误,所以对 cookie,session, token作了一下对比,相信大家看完肯定有收获!

Cookie

1991 年 HTTP 0.9 诞生了,当时只是为了满足大家浏览 web 文档的要求 ,所以只有GET请求,浏览完了就走了,两个连接之间是没有任何联系的,这也是 HTTP 为无状态的原因,因为它诞生之初就没有这个需求。

但随着交互式 Web 的兴起(所谓交互式就是你不光可以浏览,还可以登录,发评论,购物等用户操作的行为),单纯地浏览web已经无法满足人们的要求,比如随着网上购物的兴起,需要记录用户的购物车记录,就需要有一个机制记录每个连接的关系,这样我们就知道加入购物车的商品到底属于谁了,于是Cookie就诞生了。

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 。

工作机制如下

以加入购物车为例,每次浏览器请求后 server 都会将本次商品 id 存储在 Cookie 中返回给客户端,客户端会将Cookie保存在本地,下一次再将上次保存在本地的 Cookie 传给 server 就行了,这样每个 Cookie都保存着用户的商品id,购买记录也就不会丢失了

仔细观察上图相信你不难发现随着购物车内的商品越来越多,每次请求的cookie也越来越大,这对每个请求来说是一个很大的负担,我只是想将一个商品加入购买车,为何要将历史的商品记录也一起返回给 server?购物车信息其实已经记录在server 了,浏览器这样的操作岂不是多此一举?怎么改进呢

Session

仔细考虑下,由于用户的购物车信息都会保存在 Server 中,所以在Cookie里只要保存能识别用户身份的信息,知道是谁发起了加入购物车操作即可,这样每次请求后只要在Cookie里带上用户的身份信息,请求体里也只要带上本次加入购物车的商品 id,大大减少了 cookie的体积大小,我们把这种能识别哪个请求由哪个用户发起的机制称为Session(会话机制),生成的能识别用户身份信息的字符串称为sessionId,它的工作机制如下

可以看到通过这种方式再也不需要在 cookie 里传所有的购物车的商品 id 了,大大减轻了请求的负担!

另外通过上文不难观察出 cookie 是存储在 client 的,而 session 保存在 server,sessionId 需要借助cookie的传递才有意义。

session 的痛点

看起来通过 cookie + session 的方式是解决了问题, 但是我们忽略了一个问题,上述情况能正常工作是因为我们假设server是单机工作的,但实际在生产上,为了保障高可用,一般服务器至少需要两台机器,通过负载均衡的方式来决定到底请求该打到哪台机器上。

balance

如图示:客户端请求后,由负载均衡器(如 Nginx)来决定到底打到哪台机器

假设登录请求打到了 A 机器,A 机器生成了 session 并在 cookie 里添加sessionId返回给了浏览器,那么问题来了:下次添加购物车时如果请求打到了 B 或者 C,由于 session 是在 A 机器生成的,此时的 B,C是找不到 session的,那么就会发生无法添加购物车的错误,就得重新登录了,此时请问该怎么办。主要有以下三种方式

1、session 复制

A 生成 session 后复制到 B, C,这样每台机器都有一份 session,无论添加购物车的请求打到哪台机器,由于session都能找到,故不会有问题

balance (1)

这种方式虽然可行,但缺点也很明显:

  • 同一样的一份 session 保存了多份,数据冗余
  • 如果节点少还好,但如果节点多的话,特别是像阿里,微信这种由于 DAU 上亿,可能需要部署成千上万台机器,这样节点增多复制造成的性能消耗也会很大。

2、session 粘连

这种方式是让每个客户端请求只打到固定的一台机器上,比如浏览器登录请求打到 A 机器后,后续所有的添加购物车请求也都打到 A 机器上,Nginx的sticky 模块可以支持这种方式,支持按 ip 或 cookie 粘连等等,如按 ip 粘连方式如下

这样的话每个 client 请求到达 Nginx 后,只要它的 ip 不变,根据 ip hash 算出来的值会打到固定的机器上,也就不存在session找不到的问题了,当然不难看出这种方式缺点也是很明显,对应的机器挂了怎么办?

3、session 共享

这种方式也是目前各大公司普遍采用的方案,将 session 保存在 redis,memcached等中间件中,请求到来时,各个机器去这些中间件取一下session 即可。

缺点其实也不难发现,就是每个请求都要去 redis 取一下 session,多了一次内部连接,消耗了一点性能,另外为了保证redis的高可用,必须做集群,当然了对于大公司来说, redis 集群基本都会部署,所以这方案可以说是大公司的首选了。

Token:no session!

通过上文分析我们知道通过在服务端共享 session 的方式可以完成用户的身份定位,但是不难发现也有一个小小的瑕疵:搞个校验机制我还得搭个redis集群?大厂确实 redis 用得比较普遍,但对于小厂来说可能它的业务量还未达到用 redis 的程度,所以有没有其他不用 server 存储session的用户身份校验机制呢,这就是我们今天要介绍的主角:token。

首先请求方输入自己的用户名,密码,然后 server 据此生成 token,客户端拿到 token 后会保存到本地,之后向 server请求时在请求头带上此token 即可。

相信大家看了上图会发现存在两个问题

1、 token 只存储在浏览器中,服务端却没有存储,这样的话我随便搞个 token 传给 server 也行?

答:server 会有一套校验机制,校验这个 token 是否合法。

2、怎么不像 session 那样根据 sessionId 找到 userid 呢,这样的话怎么知道是哪个用户?

答:token 本身携带 uid 信息

第一个问题,如何校验 token 呢?我们可以借鉴 HTTPS 的签名机制来校验。先来看 jwt token 的组成部分

可以看到 token 主要由三部分组成

当 server 收到浏览器传过来的 token 时,它会首先取出 token 中的 header + payload,根据密钥生成签名,然后再与token中的签名比对,如果成功则说明签名是合法的,即 token 是合法的。而且你会发现 payload 中存有我们的 userId,所以拿到 token后直接在payload 中就可获取 userid,避免了像 session 那样要从 redis 去取的开销

画外音:header, payload 实际上是以 base64 的形式存在的,文中为了描述方便,省去了这一步。

你会发现这种方式确实很妙,只要 server 保证密钥不泄露,那么生成的 token 就是安全的,因为如果伪造token的话在签名验证环节是无法通过的,就此即可判定 token 非法。

可以看到通过这种方式有效地避免了 token 必须保存在 server 的弊端,实现了分布式存储,不过需要注意的是,token 一旦由server生成,它就是有效的,直到过期,无法让 token 失效,除非在 server 为 token 设立一个黑名单,在校验token前先过一遍此黑名单,如果在黑名单里则此 token 失效,但一旦这样做的话,那就意味着黑名单就必须保存在 server,这又回到了session的模式,那直接用 session 不香吗。所以一般的做法是当客户端登出要让 token 失效时,直接在本地移除 token即可,下次登录重新生成 token就好。

另外需要注意的是 token 一般是放在 header 的 Authorization 自定义头里,不是放在 Cookie里的,这主要是为了解决跨域不能共享Cookie 的问题 (下文详述)

Cookie 与 Token 的简单总结

Cookie 有哪些局限性?

1、 Cookie 跨站是不能共享的,这样的话如果你要实现多应用(多系统)的单点登录(SSO),使用 Cookie来做需要的话就很困难了(要用比较复杂的trick 来实现,有兴趣的话可以看文末参考链接)

画外音: 所谓单点登录,是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

但如果用 token 来实现 SSO 会非常简单,如下

只要在 header 中的 authorize 字段(或其他自定义)加上 token 即可完成所有跨域站点的认证。

2、 在移动端原生请求是没有 cookie 之说的,而 sessionid 依赖于 cookie,sessionid 就不能用 cookie来传了,如果用token 的话,由于它是随着 header 的 authoriize 传过来的,也就不存在此问题,换句话说token天生支持移动平台,可扩展性好

综上所述,token 具有存储实现简单,扩展性好这些特点。

token 有哪些缺点

那有人就问了,既然 token 这么好,那为什么各个大公司几乎都采用共享 session 的方式呢,可能很多人是第一次听到 token,token不香吗?token 有以下两点劣势:

1、 token 太长了

token 是 header, payload 编码后的样式,所以一般要比 sessionId 长很多,很有可能超出 cookie的大小限制(cookie一般有大小限制的,如 4kb),如果你在 token 中存储的信息越长,那么 token本身也会越长,这样的话由于你每次请求都会带上token,对请求来是个不小的负担

2、 不太安全

网上很多文章说 token 更安全,其实不然,细心的你可能发现了,我们说 token 是存在浏览器的,再细问,存在浏览器的哪里?既然它太长放在cookie里可能导致 cookie 超限,那就只好放在 local storage 里,这样会造成安全隐患,因为 local storage这类的本地存储是可以被JS 直接读取的,另外由上文也提到,token一旦生成无法让其失效,必须等到其过期才行,这样的话如果服务端检测到了一个安全威胁,也无法使相关的 token失效。

所以 token 更适合一次性的命令认证,设置一个比较短的有效期

误解: Cookie 相比 token 更不安全,比如 CSRF 攻击

首先我们需要解释下 CSRF 攻击是怎么回事

攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过(cookie里带来sessionId 等身份认证的信息),所以被访问的网站会认为是真正的用户操作而去运行。

比如用户登录了某银行网站(假设为http://www.examplebank.com/,并且转账地址为http://www.examplebank.com/withdraw?amount=1000&transferTo=PayeeName),登录后cookie里会包含登录用户的 sessionid,攻击者可以在另一个网站上放置如下代码

那么如果正常的用户误点了上面这张图片,由于相同域名的请求会自动带上 cookie,而 cookie里带有正常登录用户的sessionid,类似上面这样的转账操作在 server 就会成功,会造成极大的安全风险

CSRF 攻击的根本原因在于对于同样域名的每个请求来说,它的 cookie 都会被自动带上,这个是浏览器的机制决定的,所以很多人据此认定cookie不安全。

使用 token 确实避免了CSRF 的问题,但正如上文所述,由于 token 保存在 local storage,它会被JS读取,从存储角度来看也不安全(实际上防护 CSRF 攻击的正确方式是用 CSRF token)

所以不管是 cookie 还是 token,从存储角度来看其实都不安全,都有暴露的风险,我们所说的安全更多的是强调传输中的安全,可以用HTTPS协议来传输, 这样的话请求头都能被加密,也就保证了传输中的安全。

其实我们把 cookie 和 token 比较本身就不合理,一个是存储方式,一个是验证方式,正确的比较应该是 session vs token。

总结

session 和 token 本质上是没有区别的,都是对用户身份的认证机制,只是他们实现的校验机制不一样而已(一个保存在 server,通过在redis等中间件获取来校验,一个保存在 client,通过签名校验的方式来校验),多数场景上使用 session会更合理,但如果在单点登录,一次性命令认证上使用token 会更合适,最好在不同的业务场景中合理选型,才能达到事半功倍的效果。

本文转载自微信公众号「码海」,可以通过以下二维码关注。转载本文请联系码海公众号。

推荐系统

  • 电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    语言:中文版系统大小:2.98GB系统类型:Win8

    电脑公司Ghost Win8.1x32位纯净版V2022年7月版本集成了自2022流行的各种硬件驱动,首次进入系统即全部硬件已安装完毕。电脑公司Ghost Win8.1x32位纯净版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,精心挑选的系统维护工具,加上绿茶独有

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户