深度剖析JWT

前言:

大家好,我是Felix。祝大家周一愉快!今天我们来细致的讨论一下jwt,以及jwt的使用姿势。

什么是jwt

在此之前,我们先了解一下什么是token。只要是有过项目经验的朋友,应该都知道,token就是一个令牌,相当于是一个认证。用户初次登陆,服务端会生成一个token,前端会保存起来。客户端下次来访问我的应用,会带着token过来,如果我验证后,你的token是正确,且未过期,我就可以让你访问我的应用,否则跳转到登陆页面。

但是,传统这种token会有一些问题,如下:

服务端会保存token,这样的话,服务端相对来说会有存储压力
token能够存储的信息有限,如果说我还想要通过token拿到用户的其他信息,那就避免不了db的访问
token缺少一定的安全性,token一般都是直接对于用户信息进行加密存储,比如base加密等
不太容易扩展,因为存储在服务端,当你新增服务或者做集群时候,都会有额外的工作量

因此,为了解决这些问题,jwt也就应运而生。JWT是json web token。 可以说它是token的升级版,具有良好的安全性和可扩展性,灵活性。

jwt的构成

jwt由三部分构成

- header
- payload
- signature
header

头部通常由两部分构成,token的类型以及签名所使用的算法,然后通过BASE64加密后即得到了header部分

{
  "alg": "HS256",
  "typ": "JWT"
}
payload

载荷是一组声明,这些声明包含了有关用户的信息。声明被分为三种类型:注册声明、公共声明和私有声明。

- 注册声明:这些是一组预定义的声明,不是强制的,但建议使用,以提供一组有用的、可互操作的声明。例如:iss(签发者)、exp(过期时间)、sub(主题)、aud(受众)等。
- 公共声明:这些是可以由使用JWT的人随意定义的声明。
- 私有声明:这些是在同意使用这些声明的各方之间共享的自定义声明。
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
signature

签名用于验证消息的完整性和真实性。它是通过将头部和载荷进行编码,然后使用密钥和头部中指定的算法进行签名计算得到的。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

最终,jwt就类似于下方的例子(由三部分构成,用 . 隔开)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

那在java中如何使用JWT呢

在这里插入图片描述

可以看到在项目中,使用JWT就是这样一个步骤,那如何去生成JWT以及如何去校验呢?

首先要引入必要的依赖
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>
定义一个工具类

这里我弄得比较简单,搞了一个工具类,大家可以在项目中做自定义的扩展

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {

    // 密钥,应该保存在安全的地方,不要硬编码在代码中
    private static final String SECRET_KEY = "your_secret_key";

    // 生成JWT
    public static String generateToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("sub", userId);
        claims.put("iat", new Date());

        return Jwts.builder()
        .setClaims(claims)
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
        .compact();
    }

    // 验证JWT
    public static boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 解析JWT获取声明
    public static Map<String, Object> getClaims(String token) {
        return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
    }

    public static void main(String[] args) {
        String token = generateToken("123");
        System.out.println("Generated Token: " + token);

        boolean isValid = validateToken(token);
        System.out.println("Is Token Valid: " + isValid);

        Map<String, Object> claims = getClaims(token);
        System.out.println("Claims: " + claims);
    }
}

我们把结果输出,就可以看到JWT的组成,以及校验是否有效,以及可以看到jwt声明中的东西。

当然,这个声明其实很自由,你可以自定义你的key以及value。

当然,我们可以把这个校验放到web项目的过滤器里面,这样就具有通用性了,大家可以试一下,至于过滤器如何使用可以参考我之前的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值