本文的完整示例代码,见github仓库。小q只在文中介绍最关键的代码块。
https://github.com/yuanluoji/purestart-springboot-jwt
复制代码
关于jwt是什么,这里就不再啰嗦了。总体来讲,它有Header
、Payload
、Signature
三个部分,每一部分,都有一些细分的属性,这个原理扫一眼就可以,对我们的使用没有实质性的帮助。
使用jwt
可以让后台服务彻底的无状态化,让登录这个过程无需session的参互,这样服务端就会获得强大的横向扩容能力,前面的nginx
也不用配置ip_hash
这样蛋疼的东西。
我发现很多jwt的代码实例,都写的非常的复杂模糊。尤其是和SpringBoot的集成上,由于SpringSecurity的参与,这个过程更加的复杂。
本篇文章将主要介绍和SpringBoot的集成,让jwt真正走到实践中来。
首先,我们来看一看jwt的外衣是什么样子。就是下面这一长串。
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ5dWFubHVvamkiLCJpYXQiOjE2MDI0OTA0NDEsImV4cCI6MTYwMjQ5MjI0MX0.Qrz30s56F--cQu_fs0LWQhiZtcoLbdAuQK6dIVk4b_aSZ5is8nTs1bR7mh0qefZdiFvFk4N__sg0UouKbhH8_g
复制代码
敏感的同学一眼就能看出来,最后一步是通过base64
编码的。使用官方的html页面进行解码,可以看到它也仅仅是编码而已,其中的内容并没有加密。我们可以轻而易举的从Playload中,获取yuanluoji
这样的字眼。
1. JWT使用
使用JWT,我们是期望获得登陆验证功能的,用它来替换Cookie,用它来模拟Session。大体使用流程如下:
- 前端提交用户名和密码到任意一台服务器
- 服务器验证用户名和密码(
spring security
或者shiro
) - 如果验证成功,将使用jwt的api生成一个token
- 这个token将会返回给前端,前端将会把它保存起来(cookie、上下文或者其他),之后每次请求,都把这个token加在http头里发送到服务端
- 服务端能够验证token的合法性,因为里面有过期时间和防篡改机制,所以token需要完整发送
在Java中,比较流行的有两个包。一个是官方auth0的,不过好像因为使用比较复杂所以用的较少;另外一个就是jjwt。通过pom可以直接引入它。
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
复制代码
先来看一下Jwt的使用方式。首先是签发token的代码,片段如下:
public String generateToken(Map<String, Object> claims, String subject) {
Date now = Calendar.getInstance().getTime();
return Jwts.builde