JWT工具类

一、代码展示

@Component
public class JwtUtil {
    // 有效期
    private static final long JWT_EXPIRE = 12*60*60*1000L;  //12小时
    // 令牌秘钥
    private static final String JWT_KEY = "glxy2019zx";

    public  String createToken(Object data){
        // 当前时间
        long currentTime = System.currentTimeMillis();
        // 过期时间
        long expTime = currentTime+JWT_EXPIRE;
        // 构建jwt
        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID()+"")
                .setSubject(JSON.toJSONString(data))
                .setIssuer("system")
                .setIssuedAt(new Date(currentTime))
                .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY)) //对称加密, 对密匙转码
                .setExpiration(new Date(expTime));
        return builder.compact();
    }

    private SecretKey encodeSecret(String key){
        byte[] encode = Base64.getEncoder().encode(key.getBytes());
        SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES");
        return  aes;
    }

    public Claims parseToken(String token){
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY))
                .parseClaimsJws(token)
                .getBody();
        return body;
    }

    public <T> T parseToken(String token,Class<T> clazz){
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY))
                .parseClaimsJws(token)
                .getBody();
        return JSON.parseObject(body.getSubject(),clazz);
    }

}

二、pom文件

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

三、JWT

1、 什么是JWT?

JWT(json web token),它并不是一个具体的技术实现,而更像是一种标准。

JWT规定了数据传输的结构,一串完整的JWT由三段落组成,每个段落用英文句号连接(.)连接,他们分别是:Header、Payload、Signature,所以,常规的JWT内容格式是这样的:AAA.BBB.CCC

并且,这一串内容会base64加密;也就是说base64解码就可以看到实际传输的内容。接下来解释一下这些内容都有什么作用。

Header

Header包含加密的方式、type。

Payload

Payload这里就会包含实际传递的参数内容。记住,在这里不要传递那些很敏感的数据,因为只要base64解码就可以看到,除非你还额外加密一层。

Signature
它主要决定了Header、Payload有没有被人篡改;如果内容被篡改,那么这条JWT将会被视为无效。

2、应用场景

基本上绝大部分的人都用JWT做登录授权,它相比原先的session、cookie来说,更快更安全,跨域也不再是问题,更关键的是更加优雅~

当然它也可以用来传递数据,只不过我个人觉得做传输不太好用(实际上我想市场也这么觉得),原因几点:

1、如果是公开展示数据的话,我何必先加签才返回呢?

2、如果是私密数据的话,人家base64解码就能看到,不合适吧?即便我把payload内容加密,可这样一来就加密好几次了,我直接用别的加密手段它不香么?

或许是目前的业务需求并没有很契合。

3、验证

在这里插入图片描述

### JWT 工具类实现示例 以下是基于 JavaJWT 工具类实现示例,该工具类支持创建和解析 JSON Web Token (JWT),并提供了签名验证功能以防止篡改[^2]。 ```java import io.jsonwebtoken.*; import java.util.Date; import java.util.Map; public class JwtUtils { private static final String SECRET_KEY = "your_secret_key"; // 替换为实际使用的密钥 /** * 创建 JWT * * @param claims 自定义载荷数据 * @param ttlMillis 过期时间(毫秒) * @return JWT 字符串 */ public static String createJwt(Map<String, Object> claims, long ttlMillis) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); return Jwts.builder() .setClaims(claims) // 设置自定义载荷 .setIssuedAt(now) // 设置签发时间 .setExpiration(new Date(nowMillis + ttlMillis)) // 设置过期时间 .signWith(signatureAlgorithm, SECRET_KEY.getBytes()) // 使用 HMAC 签名算法和密钥进行签名 .compact(); } /** * 解析 JWT 并返回其中的 Claims 数据 * * @param jwtToken 待解析的 JWT 字符串 * @return Claims 对象 * @throws ExpiredJwtException 如果令牌已过期则抛出异常 * @throws UnsupportedJwtException 如果不支持当前令牌类型则抛出异常 * @throws MalformedJwtException 如果令牌格式错误则抛出异常 * @throws SignatureException 如果签名验证失败则抛出异常 */ public static Claims parseJwt(String jwtToken) throws JwtException { return Jwts.parserBuilder() .setSigningKey(SECRET_KEY.getBytes()) .build() .parseClaimsJws(jwtToken) .getBody(); } } ``` 上述代码实现了两个核心方法: 1. **`createJwt` 方法**:用于生成带有指定有效时间和自定义载荷的 JWT。通过 `SignatureAlgorithm.HS256` 和预设的密钥对生成的令牌进行签名,从而确保其不可被随意篡改。 2. **`parseJwt` 方法**:用于解析传入的 JWT,并提取其中的 Claims 数据。如果令牌已经过期、格式非法或者签名验证失败,则会分别抛出对应的异常[^3]。 --- ### 防止 JWT 被篡改的关键机制 为了防止 JWT 被恶意修改或伪造,在生成 JWT 时会对整个头部和载荷部分计算哈希值,并将其作为签名附加到最终的字符串中。当接收方收到此令牌后,可以通过相同的密钥重新计算签名并与原始签名对比来验证其真实性。 例如,在上面的 `parseJwt` 方法中,调用了 `.setSigningKey(SECRET_KEY.getBytes())` 来设置解码所需的密钥。只有持有相同密钥的一方才能够成功完成校验过程;任何试图更改负载内容的行为都会破坏原有的签名结构,进而导致验证失败。 --- ### 测试 JWT 的有效期 下面展示了一个简单的单元测试用例,演示如何利用前面提到的工具类检测某个特定时间段内的 token 是否仍然可用: ```java @Test public void testJwtValidityPeriod() throws Exception { Map<String, Object> claims = Map.of("username", "testUser"); // 创建一个仅持续三秒钟的有效令牌 String shortLivedJwt = JwtUtils.createJwt(claims, 3_000L); Thread.sleep(4_000); // 让线程休眠超过设定时限 try { JwtUtils.parseJwt(shortLivedJwt); fail("Expected an exception due to expired token."); } catch (ExpiredJwtException e) { System.out.println("Caught expected expiration error: " + e.getMessage()); } } ``` 在此例子中,我们故意让程序等待超出预期存活周期后再尝试解读刚才生产的短命凭证。不出所料的话,应该触发相应的超时期限警告消息。 --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值