传说中的jwt,我们来征服一下

关于jwt是什么 , 这里就不再啰嗦了 。 总体来讲 , 它有Header、Payload、Signature三个部分 , 每一部分 , 都有一些细分的属性 , 这个原理扫一眼就可以 , 对我们的使用没有实质性的帮助 。
使用jwt可以让后台服务彻底的无状态化 , 让登录这个过程无需session的参互 , 这样服务端就会获得强大的横向扩容能力 , 前面的nginx也不用配置ip_hash这样蛋疼的东西 。
传说中的jwt,我们来征服一下文章插图
我发现很多jwt的代码实例 , 都写的非常的复杂模糊 。 尤其是和SpringBoot的集成上 , 由于SpringSecurity的参与 , 这个过程更加的复杂 。
本篇文章将主要介绍和SpringBoot的集成 , 让jwt真正走到实践中来 。
首先 , 我们来看一看jwt的外衣是什么样子 。 就是下面这一长串 。
【传说中的jwt,我们来征服一下】敏感的同学一眼就能看出来 , 最后一步是通过base64编码的 。 使用官方的html页面进行解码 , 可以看到它也仅仅是编码而已 , 其中的内容并没有加密 。 我们可以轻而易举的从Playload中 , 获取yuanluoji这样的字眼 。
传说中的jwt,我们来征服一下文章插图
1. JWT使用使用JWT , 我们是期望获得登陆验证功能的 , 用它来替换Cookie , 用它来模拟Session 。 大体使用流程如下:

  1. 前端提交用户名和密码到任意一台服务器
  2. 服务器验证用户名和密码(spring security或者shiro)
  3. 如果验证成功 , 将使用jwt的api生成一个token
  4. 这个token将会返回给前端 , 前端将会把它保存起来(cookie、上下文或者其他) , 之后每次请求 , 都把这个token加在http头里发送到服务端
  5. 服务端能够验证token的合法性 , 因为里面有过期时间和防篡改机制 , 所以token需要完整发送
在Java中 , 比较流行的有两个包 。 一个是官方auth0的 , 不过好像因为使用比较复杂所以用的较少;另外一个就是jjwt 。 通过pom可以直接引入它 。
io.jsonwebtoken jjwt-api 0.11.2 io.jsonwebtoken jjwt-impl 0.11.2 runtime io.jsonwebtoken jjwt-jackson 0.11.2 runtime先来看一下Jwt的使用方式 。 首先是签发token的代码 , 片段如下:
public String generateToken(Map claims, String subject) {Date now = Calendar.getInstance().getTime();return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(now).setExpiration(new Date(System.currentTimeMillis() + expire * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact();}其中 , 有几个比较重要的参数需要说明一下:
  • subject 签发的主体 , 比如用户名 。 其实它也是放在claims中的 。
  • claims 一些附加信息 , 也就是playload中的内容 。 由于它是一个HashMap , 所以你大可以向里面仍你所需要的所有信息
  • expiration 签发日期和失效日期 , 在验证的时候可以使用
  • secret 加密的密钥 , 用来验证前面签发的内容
我们同样来看一下它的验证代码 。
public Claims getClaims(String token){Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();return claims;}


推荐阅读