1139 字
约 3 分钟
0
JJWT 入门:Java 生态最主流的 JWT 库

JJWT 入门:Java 生态最主流的 JWT 库

一篇讲清楚 JJWT 是什么、为什么后端几乎都用它、以及怎么在一个 Spring Boot 项目里把它用起来。

JWT 是什么?先搞懂这个前置概念

JWT(JSON Web Token)是一种无状态的身份凭证。传统的 Session 登录,用户状态存在服务器内存里,服务器一重启或者一扩容就麻烦;JWT 把用户身份直接编码成一个带签名的字符串发给客户端,之后每次请求带上它,服务器只要验签就能确认身份,不需要存任何会话状态。

一个 JWT 长这样:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMDAxIiwiZXhwIjoxNzUwMDAwMDAwfQ.7Fb3x...

用 . 分隔成三段:Header(用什么算法签名)、Payload(存了什么信息,比如用户 ID、过期时间)、Signature(用密钥对前两段做的签名)。前两段只是 Base64 编码,不是加密,谁都能解开看,所以不要往 Payload 里放密码这类敏感信息;签名的作用是保证内容没被篡改——改了任何一个字符,验签就会失败。

为什么选 JJWT

Java 生态里能处理 JWT 的库不少,JJWT 是最主流的选择,原因有三个:

  1. API 符合直觉。构建、解析、验签都是链式调用,看方法名就知道在干什么。
  2. 类型安全。解析出来的是强类型的 Claims 对象,不用自己手写 JSON 解析。
  3. 维护活跃。从 jjwt 0.x 一路迭代到 0.12.x,安全补丁跟进及时。

Spring Boot 项目引入依赖(以 0.12.x 为例):

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.12.6</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.12.6</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.12.6</version>
    <scope>runtime</scope>
</dependency>

三个包的分工很清晰:jjwt-api 是编译期接口,jjwt-impl 是运行时实现,jjwt-jackson 负责序列化。实现依赖设成 runtime,能防止代码不小心依赖到实现细节。

生成一个 Token

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;

public class JwtUtil {

    // 密钥至少 32 字节(HS256 要求),生产环境从配置读取,不要硬编码
    private static final SecretKey KEY =
            Keys.hmacShaKeyFor("my-super-secret-key-at-least-32-bytes!".getBytes(StandardCharsets.UTF_8));

    /** 签发 token:塞入用户 ID,24 小时后过期 */
    public String createToken(Long userId) {
        return Jwts.builder()
                .subject(String.valueOf(userId))
                .issuedAt(new Date())
                .expiration(new Date(System.currentTimeMillis() + 24 * 3600_000))
                .signWith(KEY)
                .compact();
    }
}

链式调用的每一步都在「声明这个 token 是什么样的」:subject 放主体标识,expiration 设过期时间,signWith 用密钥签名。最后 compact() 输出字符串。

解析与验签

/** 验签 + 解析,一步完成;签名不对或已过期会抛异常 */
public Long parseToken(String token) {
    Claims claims = Jwts.parser()
            .verifyWith(KEY)
            .build()
            .parseSignedClaims(token)
            .getPayload();
    return Long.valueOf(claims.getSubject());
}

关键是这一步同时做了两件事:验签(确认没被篡改)和检查过期(exp 过了直接抛 ExpiredJwtException)。所以业务代码里只要 try-catch 一下,就能区分「token 无效」和「token 过期」两种情况给出不同提示。

在 Spring Boot 里落地

典型的用法是配一个过滤器:请求进来先检查 Authorization 头里的 token,验过了就把用户信息放进请求上下文,放行;验不过直接返回 401。

客户端登录 → 服务端签发 token → 客户端存起来(localStorage/cookie)
    → 每次请求带 Authorization: Bearer <token>
    → 服务端过滤器验签 → 通过则处理业务

几个生产环境的要点:

  • 密钥管理:密钥泄露等于所有人都能伪造身份,务必放在环境变量或受限配置文件里,不进 Git。
  • 过期时间要短:access token 通常 30 分钟到 24 小时;想做「记住我」,用 refresh token 机制而不是把 access token 拉长到一个月。
  • HTTPS 是前提:token 明文传输一旦被截获就等于账号被冒用,生产环境必须全程 HTTPS。
  • 无法主动作废是 JWT 的天然短板:签出去的 token 在过期前一直有效。需要「立即踢下线」能力时,配合 Redis 存黑名单,或者干脆短过期 + refresh 轮换。

小结

JJWT 解决的是「Java 里怎么方便又安全地生成和校验 JWT」这一件事。理解了三段结构、验签即校验这两个核心,API 只是顺水推舟。本站的登录鉴权就是这条链路:登录签发 token,之后所有请求靠它无状态通行——你在多个设备同时登录互不干扰,服务器也不用存任何会话。

JJWT 入门:Java 生态最主流的 JWT 库
http://www.clxhxhhr.top/posts/3705/
作者
clxstart
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。