什么是JWT
jwt全称Json-Wen-Token------基于json的web令牌,用来当做登录凭证、代替传统 Session 的一串加密字符串。
- Session:小区物业给你一张纸质门禁卡,物业后台登记你的信息;卡丢了物业可以直接作废。
- JWT:一张自带全部个人信息、并且盖了物业钢印的门禁卡 卡片本身就写着你的用户 ID、名字;钢印用来防止你私自篡改卡片信息。 后端不需要往数据库 / Redis 存一份会话,拿到卡片就能认出你是谁。
JWT的结构
- header (头部):加密算法,例如 HS512
- payload (载荷):存放用户数据:userId、username、过期时间
- signature (签名,钢印) 使用你后端自定义密钥加密签名; 一旦载荷内容被人篡改,签名就校验失败,后端直接判定令牌非法。
JWT使用流程
- 用户登录成功,后端打包用户信息,生成 JWT 令牌发给前端;
- 前端每次请求带上这个令牌;
- 后端解析、校验签名,确认没有被篡改,取出登录用户;
- 项目额外搭配 Redis:用来控制会话过期、强制下线(JWT 本身无状态,没法主动作废)。
JWT的签名是如何生成的
签名 = 头部 + 载荷 + 你的密钥,通过加密算法算出的一串验证码
最终完整 token:header串.payload串.签名串
建议使用SecureRandom生成密钥:
SecureRandom 是密码级别的强随机,不要用普通 Random。
java
import java.security.SecureRandom;
import java.util.Base64;
public class JwtSecretGen {
public static void main(String[] args) {
// HS512 需要 64 字节密钥
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
String secret = Base64.getEncoder().encodeToString(key);
System.out.println(secret);
}
}
也可以使用Linux快速生成:
java
openssl rand -base64 64
使用hutool工具包操作JWT
1.引入1依赖
java
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.26</version>
</dependency>
2.生成Token
java
import cn.hutool.jwt.JWTUtil;
import java.util.HashMap;
import java.util.Map;
public class Test {
// HS512密钥,生产环境64字节以上
private static final byte[] SECRET = "你的随机密钥".getBytes();
public static void main(String[] args) {
Map<String,Object> payload = new HashMap<>();
payload.put("userId",1001);
payload.put("username","admin");
// 过期时间:24小时(毫秒)
payload.put("expire_time",System.currentTimeMillis() + 24*3600*1000);
// 创建令牌
String token = JWTUtil.createToken(payload,SECRET);
System.out.println(token);
}
}
3.校验签名,过期时间
java
// 校验签名合法性、检查是否过期
boolean ok = JWTUtil.verify(token,SECRET);
4.解析获取载荷中的数据
java
JWT jwt = JWTUtil.parseToken(token);
Integer userId = (Integer) jwt.getPayload("userId");
String username = (String) jwt.getPayload("username");
链式写法
java
import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.signers.JWTSignerUtil;
byte[] secret = "密钥".getBytes();
String token = JWT.create()
.setPayload("userId",1001)
.setPayload("username","admin")
.setIssuedAt(DateUtil.date()) //签发时间
.setExpiresAt(DateUtil.offsetHour(DateUtil.date(),24)) //过期时间
.setSigner(JWTSignerUtil.hs512(secret)) //指定HS512加密算法
.sign();