关于JWT 的那些事儿

JWT 英文名是 Json Web Token,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用于跨域身份验证。

JWT 以 JSON 对象的形式安全地传递信息。因为存在数字签名,因此所传递的信息是安全的。

为什么需要JWT ?

在了解 JWT 之前我们先来看一下为什么需要 JWT

传统方式的局限性

传统的登录方式:用户端输入用户名密码,服务器端校验通过,根据用户信息生成一个 token,将 token 和 user_id 存到数据库或 session会话 中,并将 token 返回给前端,存入cookie,浏览器每次请求都会带上 cookie,服务端根据cookie中的 token 查询用户(如user_id),验证用户有效性。

传统方式存在以下弊端:

① 如果出现XSS(跨站脚本攻击)漏洞,由于 cookie 可以被 js 读取,XSS 漏洞会导致用户 token 被泄露。解决方案:

  • 设置 httpOnly。这样的话 cookie 将不会被 js 读取,浏览器会自动将它加到请求头信息中,但是带来了新的问题,很容易被XSRF(跨站请求伪造)攻击,因为只要当前浏览器开着,另一个界面可以很容易地跨站请求这个界面的内容,因为cookie会被默认发送出去。
  • 设置 secure。这样 cookie 就只能通过 https 传输,可以过滤掉一些使用 http 协议请求的 XSS 注入。

② 将验证信息存到数据库中,每次验证的时候,都需要去数据库中查询,增加了数据库的查询和存储开销。

③ 如果将 token 存到 session 中,也会增加服务器的存储压力。

④ 无法横向扩展。在服务器集群或者面向服务且跨域的结构中,需要数据库来保存 Session 会话,实现多个服务器之间的会话数据共享。在单点登录中为了解决共享 Session 问题,其中一种方法是持久化 Session 数据,但是缺点也非常明显,就是架构修改很困难,验证逻辑需要重写,并且整体依赖于数据库,如果存储 Session 会话的数据库挂掉那么整个身份认证就无法使用,进而导致系统无法登录。

JWT的优势

① 可以通过 URL POST 参数或者 http header 中发送,数据量小,传输速度快。

② 自包含:负载中包含了用户所需要的所有信息,避免多次查询数据库。原来是先拿着 token 去找 user_id,现在是,JWT 的有效载荷中就包含了 user_id 等信息。这样就不需要服务器端存储 Session 信息。

JWT组成

说白了 JWT 就是一段数据,我理解的是它既代表了一种思想,又提供了具体的解决方案

JWT 是由三段字符串和两个 . 组成,类似于这样:xxxxxx.yyyyyy.zzzzzz,每个字符串代表了不同的功能。

JWT 头 Header

JWT 头描述了 JWT 元数据,是一个 JSON 对象,它的格式如下:

json{"alg":"HS256",
     "typ":"JWT"}

其中 “alg” 属性表示签名所使用的算法,JWT 签名默认的算法为 HMAC SHA256 ,

“typ” 属性表示令牌类型,这里就是 JWT。

有效载荷Payload

有效载荷是 JWT 的主体,也是个 JSON 对象。有效载荷包含三个部分:

  • 标准注册声明。它一般包括以下内容:

    iss:jwt的签发者/发行人

    sub:主题

    aud:接收方

    nbf:jwt生效时间

    exp:jwt过期时间

    iat:签发时间

    jti:jwt唯一身份标识,可以避免重放攻击

  • 公共声明。

    可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密。

  • 私有声明。

    私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。

下面这个代码段就是定义了一个有效载荷:

json{"exp":"201909181230",
     "role":"admin",
     "isShow":false}

哈希签名 Signature

哈希签名的算法主要是确保数据不会被篡改。它主要是对前面所讲的两个部分进行编码,通过 JWT 头定义的算法(“alg”:“HS256”)生成哈希。

③Signature = HMACSHA256(
		base64UrlEncode(①Header) +
		"." +
		base64UrlEncode(②Payload),
		password
)

最终

JWT = Header.Payload.Signature

JWT 使用过程

① Client 通过账号密码登录,Server 验证通过后,将用户的 id 及其他非敏感信息作为JWT Payload,将其与头部分别进行 base64 编码后签名,生成 JWT,然后将 JWT返 回给 Client。

② Client 将收到的 JWT 保存到 localStorage 或者 sessionStorage 中,跳转到登录页或请求 API,将 JWT 发送给 Server;退出登录时,Client 删除保存的 JWT 信息即可。

③ Server端进行过滤器拦截请求(验证JWT的有效性),若通过,则进行业务逻辑操作并想客户端返回数据,若不通过,则返回错误信息, Client 提示错误,跳转回登录页面。

服务端验证 JWT

服务端验证 JWT 的过程就是签名的过程,如何判判断客户端发送的 JWT 就是我刚才给你的那个?关键就在于存储在服务端的密码

JWT 最终是由 Header、Payload、Signature 三部分组成,其中签名又是由 Header 和 Payload 的编码以及密码组成,当客户端发送 JWT 过来,服务端将 Header 和 Payload 以及存储在服务端的密码(一般是加密过的,而不是明文)重新进行签名,然后将此签名与客户端发送的 JWT 中的签名进行比对,如果相同则认为客户端发送过来的这个 JWT 就是我刚才给你发送的那个,从而验证客户端身份。

这里的关键就在于存储在服务端的密码,因为密码只有服务端有,因此就保证了签名的唯一性。而从客户端发送过来的 JWT 中是无法得到的密码的,因为密码通过哈希被包含在了签名中,而哈希是不可逆的,这就避免了JWT 在传输过程中的密码泄漏问题。

JWT 应用场景

JWT 通常用来设计用户认证和授权系统,还有我们通常说的单点登录等。

JWT注意事项

在使用 JWT 时需要注意以下事项:

JWT 默认不加密,如果要写入敏感信息必须加密,可以用生成的原始令牌再次对内容进行加密;

JWT只适合向 web 端传递一些非敏感信息,因为 base64 编码是可逆的,很容易被破解;

JWT 无法使服务器保存会话状态,当令牌生成后在有效期内无法取消也不能更改;

JWT 包含认证信息,如果泄露了,任何人都可以获得令牌所有的权限;因此 JWT 有效期不能太长,对于重要操作每次请求都必须进行身份验证。

JWT本质只能是能够避免了服务端进行存储token的弊端,服务端通过采用数字签名的方式避免只进行验证而不存储,但是JWT本身的明文传输仍然是不安全,JWT可以在SSL的安全通道下进行传输。JWT最大的作用也是认证。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值