Java 中 JWT 相关知识全面解析与实战指南

Java 中 JWT 相关知识全面解析与实战指南

一、什么是 JWT?

JWT(JSON Web Token)是一种基于 JSON 格式的令牌,用于在双方之间安全地传输信息。它主要应用于认证授权场景,尤其在前后端分离项目中十分常见。

JWT 的结构

JWT 由三部分组成:

  1. Header(头部):描述 JWT 的元信息,比如签名算法。
  2. Payload(负载):存储用户的非敏感信息,如 userIdusername
  3. Signature(签名):用于验证数据完整性,确保令牌未被篡改。

一个 JWT 示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiJqb2huZG9lIiwiaWF0IjoxNjkwOTY3NjAwLCJleHAiOjE2OTA5NzEyMDB9.aWQl3zjW7dK3WY3xOt3MzIlQbK4XkwnAs8fN8LS9hEI

解码后的结构:

  1. Header:
{
  "alg": "HS256",
  "typ": "JWT"
}
  1. Payload:
{
  "userId": 123,
  "username": "johndoe",
  "iat": 1690967600,
  "exp": 1690971200
}
  1. Signature:
    由头部和负载通过指定算法(如 HMAC SHA256)加密生成,用于验证数据完整性。

二、JWT 的核心特点

  1. 无状态性:无需服务器存储令牌状态信息,每次请求携带 JWT 即可验证用户身份。
  2. 安全性:使用签名机制验证令牌完整性,防止篡改。
  3. 便携性:基于 Base64 编码,便于传输。

三、JWT 的常见应用场景

  1. 用户登录认证:用户登录成功后,返回 JWT 令牌用于后续请求认证。
  2. 接口权限控制:基于 JWT 中的角色信息决定用户是否有权访问某些接口。
  3. 前后端分离项目:通过 HTTP Header 携带 JWT 进行身份验证,简化开发流程。

四、如何在 Java 中使用 JWT

以下内容基于 Spring Boot 框架,结合 jjwt 库(io.jsonwebtoken),详细介绍 JWT 的生成、解析和验证。

1. 引入依赖

pom.xml 中添加 jjwt 依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- For JSON parsing -->
    <version>0.11.5</version>
</dependency>

2. 配置 JWT 工具类

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;

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

public class JwtUtil {
    private static final String SECRET_KEY = "mySecretKey"; // 签名密钥
    private static final long EXPIRATION_TIME = 3600000; // 1 小时(单位:毫秒)

    /**
     * 生成 JWT Token
     *
     * @param claims 自定义的负载(如用户信息)
     * @return JWT 字符串
     */
    public static String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date()) // 签发时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 过期时间
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 签名算法
                .compact();
    }

    /**
     * 验证 Token 并解析
     *
     * @param token JWT 字符串
     * @return 解析后的 Claims
     */
    public static Claims validateToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 检查 Token 是否过期
     *
     * @param claims JWT 的 Claims
     * @return 是否过期
     */
    public static boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
}

3. 实际项目中的使用

用户登录认证

Controller 示例:

@RestController
@RequestMapping("/auth")
public class AuthController {
    @PostMapping("/login")
    public ResponseEntity<Map<String, Object>> login(@RequestBody Map<String, String> loginData) {
        String username = loginData.get("username");
        String password = loginData.get("password");
        
        // 模拟用户验证
        if ("admin".equals(username) && "123456".equals(password)) {
            Map<String, Object> claims = new HashMap<>();
            claims.put("username", username);
            claims.put("role", "admin");
            
            String token = JwtUtil.generateToken(claims);
            Map<String, Object> response = new HashMap<>();
            response.put("token", token);
            return ResponseEntity.ok(response);
        } else {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "用户名或密码错误"));
        }
    }
}
接口权限验证

JWT 拦截器配置:

import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        try {
            token = token.replace("Bearer ", "");
            Claims claims = JwtUtil.validateToken(token);
            request.setAttribute("claims", claims);
            return true;
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
    }
}

拦截器注册:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/auth/login"); // 排除登录接口
    }
}

五、总结

通过本文,您了解了 JWT 的基本原理及其在 Java 项目中的实际应用,包括:

  1. JWT 的组成与特点。
  2. 使用 jjwt 库生成和验证 Token。
  3. 在实际项目中如何结合登录认证和权限控制。

JWT 是前后端分离项目中不可或缺的一部分,掌握它可以极大地提升开发效率。如果您有任何问题,欢迎在评论区留言讨论!

记得点赞、收藏 🎉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值