浅析JWT

Cookie-session

我们都知道JWT一般用于用户登录等需要记住的操作,在谈论JWT之前就不得不谈谈以前的cookie-session登录了 。因为http协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录(也就是说你登陆过后哪怕你刷新一下他也不认识你了,还要你继续登录);Session 和 Cookie 的主要目的就是为了弥补 HTTP 的无状态特性。

互联网服务离不开用户认证,一般流程如下:

 这就是Cookie-session方法 

Session是什么


客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session 对象,存储结构为 ConcurrentHashMap。Session 弥补了 HTTP 无状态特性,服务器可以利用 Session 存储客户端在同一个会话期间的一些操作记录,如上图所示,我们在这个过程中会存储session_id。

cookie-session机制的缺点

扩展性(scaling)不好


单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。比如 A 服务器存储了 Session,在做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大(session存储在服务端,这就增大了服务器的开销,当用户多的情况下,服务器性能会大大降低)。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端(一种非常重要的思想,让客户端帮我们存储或者做计算减少服务端的压力),每次请求都发回服务器。JWT 就是这种方案的一个代表。

安全性差:

Cookie安全性是一个大问题,因为它们是以明文形式存储,可能会造成安全风险,因为任何人都可以打开并篡改cookie。Cookie容易在客户端被发现意味着它们很容易被黑客入侵和修改。也就等于合法登陆了你的账户

能直接看到cookie

JWT

JWT 的原理

服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名 。服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

JWT的数据结构

实际的JWT就像这样

我们可以通过JSON Web Tokens - jwt.io 来解析JWT

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

JWT 的三个部分依次如下。

写成一行,就是下面的样子。

 Header部分是一个JSON对象,描述JWT的元数据

payload部分也是一个json对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

 除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

Signature 部分是对前两部分的签名,防止数据篡改。

JWT的使用方式

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

 另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

JWT的特点

对于第三点:

也就是说一个用户在手机A中登录了,然后又在手机B中登录,在过期之前手机A和B都可以登录,无法做到B登录后让A过期,如果要做到这点,就必须让服务器维护一个清单(记录该账号是否已经签发token),这样又回到session的老路了

说完JWT,你可能还是会有疑惑,这不和cookie-session差不多吗?cookie-session返回session_id,JWT返回token,那你cookie可能会被截获并修改那你token就不会了吗?

事实上,JWT可以通过Signature字段来防止token被篡改。使用私钥加密生成token  公钥解密获取token中的信息,所以如果 JWT 的Signature 都被破解了就 GG 了(比如某些开发者将网上的jwt示例直接抄过来不加修改就很容易被暴力破解)

另一方面采用https 或者 代码层面也可以做安全检测,比如ip地址发生变化,MAC地址发生变化等等,可以要求重新登录

由于token生成后无法设置该token为无效,所以只能采用设置token过期时间来生成新的refresh_token。以及应该使用HTTPS协议传输(这些都是上图特点6的内容)

除了安全性,JWT还有什么好处吗?

JWT官方给出的解释是(对比SWT与SAML):

JWT由于使用的是JSON所以比较轻量:由于JSON不像XML那么冗长,所以在编码时,它的大小也更小,使得JWT比SAML更紧凑。这使得JWT成为在HTML和HTTP环境中传递的好选择。

安全性:SWT只能使用HMAC算法由共享密钥对称签名。然而,JWT和SAML令牌可以使用X.509证书形式的公钥/私钥对进行签名。与签名JSON的简单性相比,使用XML数字签名签名XML而不引入模糊的安全漏洞是非常困难的。

JSON在各种语言都能方便的解析:JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象映射。这使得使用JWT比使用SAML断言更容易。

跨平台性:JWT在互联网规模上使用。这突出了在多个平台(尤其是移动平台)上客户端处理JSON Web令牌的方便性。

JWT的优点:

  • JWT是一种无状态身份验证机制,因为用户状态永远不会保存在数据库中。由于 JWT 是独立的,因此所有必要的信息都在那里,从而减少了来回访问数据库的需要。使用 JWT,我们不需要查询数据库来验证每个 api 调用的用户
  • 安全性,使用signature和到期时间(refresh_token),防止CSRF(跨站请求伪造漏洞)攻击。
  • JWT结构紧凑。由于其大小,它可以通过URL,POST参数或在HTTP标头中发送
  • 跨域,Cookie 绑定到单个域。在域上创建的cookie不能跨域读取,而您可以将令牌发送到您喜欢的任何域

JWT的缺点:

  • 也不是绝对安全的,如果被破解了Signature(虽然没那么简单),黑客可以随意改动 payload 的部分,达到将普通用户升级为管理员进而破坏系统等等操作
  • 相比于 cookie-session 的开箱即用, JWT 需要自己写额外的代码

JWT的最佳实践:

  • 始终为您颁发的任何令牌设置到期日期
  • 尽可能避免在 URL 参数中发送令牌
  • 包括(受众)声明(或类似声明)以指定令牌的预期接收者。这可以防止它在不同的网站上使用
  • 使颁发服务器能够吊销令牌(例如,在注销时)

参考资料:
基于Session的身份窃取 - 腾讯云开发者社区-腾讯云 (tencent.com)

JSON Web Token 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)

JSON Web Token Introduction - jwt.io

learn-json-web-tokens/README.md at master · dwyl/learn-json-web-tokens (github.com)
JWT attacks | Web Security Academy (portswigger.net)
JSON Web 令牌 (JWT) 相对于 Cookie 的优势/劣势 - 堆栈溢出 (stackoverflow.com)
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值