欢迎光临
我们一直在努力

JWT的原理与实现

JWT基本概念

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全传输信息作为JSON对象。通俗理解为:`带有防伪水印的临时身份证
它由三部分组成:

  • Header:包含算法和令牌类型(怎么加密的)
  • Payload:携带用户声明信息(一般是存的是代码里的 userId,iat,exp)
  • Signature:验证令牌完整性的签名
    (Signature=【A:Header(经过如 Base64 编码的头)+ B:Payload(经过如 Base64 编码的内容,比如 userId=1)+ C:Secret(服务器私钥,这是唯一保密的东西)】用哈希算法生成的东西)
    典型JWT格式:xxxxx.yyyyy.zzzzz eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInVzZXJuYW1lIjoiZXhhbXBsZV91c2VyIiwiZXhwIjoxNjMwNjQ5NjAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • JWT的实现

    1. 核心依赖

    首先,这个工具类是基于 Java 社区最常用的 JWT 库 jjwt 实现的。在你的 pom.xml 里加上这个依赖:

    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
    </dependency>

    2. 拒绝硬编码:配置文件

    我们利用 Spring 的 @Value 注解,把配置参数提取到 application.yml中。这样做的好处是,将来你要修改过期时间或者更换密钥,重启一下服务就行,不用重新编译代码。

    jwt:
    # 密钥 (Secret):
    # 建议设长一点,复杂一点,防止被暴力破解。
    secret: asdfghhjttjtjtjt1111

    # 过期时间 (Expiration):
    # 单位是秒。 (60*60*24*7 = 604800)
    expiration: 604800

    3. 工具类源码深度解析

    下面是完整的 JwtUtil 代码。详细解析都在代码注释中。

    package com.example.demo.util;

    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;

    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;

    @Component // 1. 交给 Spring 管理,方便在 Service 或 Controller 里注入
    public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private Long expiration;

    /**
    * 【造证】生成 JWT 令牌
    */

    public String generateToken(Long userId) {
    // 2. 准备载荷 (Payload)
    // 我们只放 userId,因为 payload 只是 Base64 编码,不要放密码等敏感信息!
    Map<String, Object> claims = new HashMap<>();
    claims.put("userId", userId);

    return Jwts.builder()//把数据变成一串加密字符串
    .setClaims(claims) // 设置自定义数据(如userId)
    .setIssuedAt(new Date()) // 设置“发证日期”为当前时间(iat)都放到claims里面了
    // 3. 设置过期时间(exp)
    // System.currentTimeMillis() 获取当前毫秒数
    // expiration * 1000 将配置的秒转为毫秒
    .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
    // 4. 签名 (盖章)
    // 使用 HS512 这种高强度哈希算法,配合我们的 secret 密钥进行签名
    .signWith(SignatureAlgorithm.HS512, secret)
    .compact(); // 压缩生成最终的 String
    }

    /**
    * 【读证】从 token 中获取用户ID
    */

    public Long getUserIdFromToken(String token) {
    try {
    // 5. 解析 Token
    Claims claims = Jwts.parser()//把那串字符串变回原始数据(Claims)。
    .setSigningKey(secret) // 本身不判断,只是收集secret(把子弹上膛)。
    .parseClaimsJws(token)//拆解 Header,Payload然后和secret一起运算看看能否与token一致
    .getBody();

    // 拿到数据后转回 Long 类型
    return Long.valueOf(claims.get("userId").toString());
    } catch (Exception e) {
    // 如果解析过程报错(比如 Token 被篡改、格式不对),返回 null
    return null;
    }
    }

    /**
    * 【验理】验证 token 是否有效
    */

    public boolean validateToken(String token) {
    try {
    // 6. 核心验证逻辑
    // parseClaimsJws 方法非常严格,它会自动校验:
    // A. 签名是否匹配 (防止篡改)
    // B. 是否已过期 (ExpiredJwtException)
    Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
    return true;
    } catch (Exception e) {
    // 只要有异常,统统视为验证失败
    return false;
    }
    }

    /**
    * 【续期】刷新 JWT 令牌
    * 简单实现:直接签发一个新的
    */

    public String refreshToken(Long userId) {
    return generateToken(userId);
    }
    }

    4怎么用?(实战场景)

    登录接口
    用户登录成功后,你不需要像以前那样存 Session,直接发证:

    @Autowired
    private JwtUtil jwtUtil;

    public Result login(LoginDTO loginDTO) {

    User user = userService.checkLogin(loginDTO);

    String token = jwtUtil.generateToken(user.getId());

    return Result.ok(token);
    }

    码字不易,如果觉得这篇文对你有帮助的话,请点赞,评论,收藏,欢迎在评论区留言,每一条我都会看!
    请添加图片描述

    赞(0)
    未经允许不得转载:171主机测评 » JWT的原理与实现
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址