JWT(JSON Web Token)理解与应用

什么是JWT token?

根据官网的定义,JSON Web Token(以下简称 JWT)是一套开放的标准(RFC 7519),它定义了一套简洁(compact)且 URL 安全(URL-safe)的方案,以安全地在客户端和服务器之间传输 JSON 格式的信息。通俗来讲就是一个客户端与服务端交互的凭据。其实可以理解为一种生成token的框架或规范。

为什么使用JWT,为什么使用token认证:

常见的服务端认证方法有基于 Cookie 的认证,如 session-cookie;以及 Token (令牌)认证,如 JWT。前者依赖于 cookie 而实现,在每次请求时都需要带上 cookie ,取出相应字段并与服务器端的进行对比,以实现身份的认证。而后者仅仅需要在 HTTP 的头部(header)附上 token,由服务器 check signature 即可实现,无须担心 cookie 存在的 CORS (跨域,即服务不会部署在同一台服务器上,而一个session是不能共享到其他服务器的)问题。网上有许多文章来比较token和session的优缺点,其实哪种都行,但如果是开发api接口,前后端分离,最好使用token,为什么这么说呢,因为session+cookies是基于web的。但是针对 api接口,可能会考虑到移动端,app是没有cookies和session的。

如何实现token,JWT token的组成:

token前面说了就是一个服务器与前端交互的凭据,用户可以通过这个来实现免密登陆,不用频繁的登陆,所有开发者可以针对自己开发的应用定义自己的token,只要做到不让黑客和无聊者破解,利用伪造的token来访问我们自己的系统即可;而JWT给我们提供了一种token的生成方式,且token的生成时无状态的,就是服务器不用来维护这个token,生成后交给客户端就ok了。对于JWT的token生成的原理和过程,针对java有jjwt包:
再此,阐述一下自己对JWTd的理解:

JWT token 的组成:

首先,JJWT生成的token的样例为:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.TyFCGGdGTdsrTbCPsvAp5FxQBQRTU7OkjeOz-1X5xao
分别对应的时header,payload,verify signature
header: 用户存储加密方式,样例是HS256加密方式,jjwt提供了12中加密方式,需要注意的是,加密方式是明文,只是通过base64编码后成为不可读的样子,拿到一个token通过base64解码时可读的。
payload:是属于内容部分,就是存储我们要保存到客户端的信息,一般都是包含用户的基本信息,权限信息,时间戳等信息。
标准中注册的声明 (建议但不强制使用) :
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
verify signature:签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload),secret)
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。如样式所示。

JWT token与服务端校验的流程:

jwt token默认的校验流程是无状态的,所谓无状态是服务器不用去维护token,生成后扔给客户端就ok了,之后每次交互只需要验证token的合法性就完了;有无状态的token就会有有状态的token,有状态的token的实现方式和session-cookie实现服务端认证的原理是一样的。

无状态token校验流程:

无状态token就是服务器不保存token信息,当用户登陆成功后,返回用户token,用户通过cookies或者本地存储方式保存起来,以后用户每次访问服务器都带着这个token,服务器会先根据jwt规则验证token的有效性,如果有效则让用户继续访问对应接口,如果无效则返回提示信息。
可能有人会问,无状态token如何处理过期时间呢?难道可以使用到3000年吗?这个问题可以通过token中的时间戳来解决。比如用户登陆成功的时间是2019年7月1日。那么token的时间戳字段就赋值为2019/07/01。根据需求,假如默认用户30天token过期。那么用户每次访问服务器做权限验证时,就可以验证时间戳信息,用当前服务器时间减去时间戳时间,如果大于30天就提示用户token失效,请重新登陆。
那么有些人可能还会问,如果服务器管理员注销了该用户,但是该用户用之前登陆的token是否还是可以访问系统呢?这个可以通过在服务器建立一个注销用户表,在验证jwt信息时,去注销用户表查询是否有该用户,如果存在的话就禁止用户访问了。当然,解决方案不知这么一种,还是看开发者实际的需求而定.

有状态token:

有状态token就是服务器保存token信息,跟web中的session实现很像。通过上边的介绍可能会觉得无状态token挺省事的,为什么还需要有状态token呢? 通过前边jwt的介绍,我们会发现,jwt的内容还是比较长的,每次客户端访问服务器都携带这么长的信息,频繁的访问服务器还是比较耗费时间和流量的。尤其在jwt的payload中存储比较多的用户信息及权限信息。token的长度会非常长。
那如何解决这个问题呢?这就要引入有状态token,我们可以想像下传统服务器session的实现,它只把session_id存储到客户端,客户端频繁访问服务器只携带session_id,然后服务器通过session_id去session中查找对应的存储信息。有状态token也是使用这个逻辑:在用户第一次登陆成功后,服务器生成jwttoken,因为jwttoken比较长,遂将其存在了服务器,然后返回客户端一个加密的tokenid,客户端每次通过这个加密的tokenid访问服务器,原理就跟session_id的流程是一样的了。
我们知道服务器的session是存储在内存中的,为了高效。同理我们将jwttoken信息也存储在服务器的内存,通用的解决方案是存储到redis中,我们知道redis的存储是基于内存的。速度会比数据库快一些(当搭建集群后redis显得尤为重要,分布式session就是通过redis解决的)。

JWT token存在的问题

不要用jwt来做session 机制的存储:
https://www.jianshu.com/p/af8360b83a9f

这两篇文章讲了jwt token 的局限性,总结如下:
1.token的时效性,因为token一但颁发在不过期的时间内是一只有效的,因为是无状态的所以后台在删除这个用户后,这个用户的token却是合法的。
2.不要用token做session机制,主要https://learnku.com/articles/22616里讲解了token做session机制所存在的安全隐患,因为token的存储方式,存储道cookie或者localstorage都会引发安全隐患,用来做session机制控制容易造成问题,总结时token做短时间的签名校验。

JWT token的评价:

对于jwt token 的原理与实习很好理解,但在jwt的应用场景上存在很大的分歧,网上各有所云,jwt用于用户的认证,在微服务的场景上,jwt做session机制看来不行。这里再讨论,我不是很理解。

博文参考:
Jwt的使用场景
讲真,别再使用JWT了!
(译)别再使用 JWT 作为 Session 系统!问题重重且很危险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值