JWT基本使用

JWT是一种开放标准,常用于授权和信息交换。它解决了传统Session认证的问题,如服务器开销和跨站请求伪造攻击。JWT由标头、有效载荷和签名三部分组成,其中签名确保内容未被篡改。本文介绍了JWT的基本使用,包括生成JWT token、解析token数据、封装工具类以及在拦截器中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JWT

JSON Web令牌简介

JSON Web Token(JWT)是一个开放标准,用于在各方之间以JSON对象安全的传输对象。

JWT能做什么?

  1. 授权

这是JWT最常见的方式。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它开销小并且可以在不同的域中使用

  1. 信息交换

在不同的数据之间进行信息交换,因为可以对JWT进行签名,所以可以确保发件人是想要的人。并且通过签名还可以判断内容是否被篡改。

传统Session认证

在这里插入图片描述

暴露的问题:

  1. 每个用户认证之后都会在服务器做一次记录,方便用户下次请求的鉴别,而session都是保存在内存中,随着用户增多,服务器开销会增大。
  2. 用户认证之后,session记录被保存在服务器的内存中,就意味着用户下次请求还要在这个服务器上,如果在分布式的应用上就限制了负载均衡的能力,限制了应用的扩展能力。
  3. 因为是基于cookie进行认证的,cookie如果被截获,服务器就是容易受到跨站请求伪造(CSRF)的攻击。

基于JWT认证
在这里插入图片描述

JWT结构

令牌组成

  1. 标头(header)
  2. 有效载荷(payload)
  3. 签名(signature)

因此。JWT(token)经常显示为:xxxx.yyyy.zzzz 一段字符串

Header

标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法(因为JWT第三部分就是进行签名),例如HMAC、SHA526或RSA。然后使用Base64编码组成JWT结构的第一部分(注意:Base64是一种编码,也就是说,它可以被翻译回以前的样子,并不是一种加密过程)。

示例(头部的默认值也是这个)
{
	"alg": "HS256",
	"typ": "JWT"
}

Payload

有效载荷是有关实体(通常是用户)和其他数据的生命,同样会使用Base64编码。(注意:此部分不要放置用户敏感信息,如密码,否则会导致信息安全 问题)

示例
{
	"sub": "123456",
	"name": "zhangsan",
	"admin": true
}

Signature

签名是编码后的第一部分+编码后的第二部分和我们提供的一个秘钥,然后使用头部规定的签名算法进行签名。签名的目的是防止头部信息被篡改。

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

JWT的第一个程序

  1. 引入依赖
        <!--引入jwt依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.1</version>
        </dependency>
  1. 生成token
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, 600);
        String token = JWT.create()// header有默认值可不用写
                .withClaim("userId", 21)//payload
                .withClaim("username", "zhangsan")
                .withExpiresAt(calendar.getTime())// token过期时间  600秒后过期
                .sign(Algorithm.HMAC256("!@sdsfsdgfdg")); // 签名
        System.out.println(token);

// 结果
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTYyMTU1MzksInVzZXJJZCI6MjEsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.Y8CrFynod_hd4983yk9azl8xXIB5YiwajFSE_B71qAk
  1. 获取token中的数据
        //创建验证对象
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256("!@sdsfsdgfdg")).build();// 注意秘钥要和生成token的秘钥一致

        DecodedJWT verify = verifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTYyMTU1MzksInVzZXJJZCI6MjEsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.Y8CrFynod_hd4983yk9azl8xXIB5YiwajFSE_B71qAk");

        System.out.println(verify.getClaim("userId").asInt());

        System.out.println(verify.getClaim("username").asString());
// 测试结果
21
zhangsan

JWT常见异常

在这里插入图片描述

封装工具类

public class JWTUtil {

    public static final String secret = "!sdsfsdgfdg";

    //获取token
    public static String getToken(Map<String, String> map){
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, 7);// 默认7天过期

        JWTCreator.Builder builder = JWT.create();

        map.forEach((k,v) -> builder.withClaim(k,v));

        String token = builder.withExpiresAt(calendar.getTime())
                .sign(Algorithm.HMAC256(secret));
        return token;
    }

    //验证合法性并获取参数
    public static DecodedJWT getDDecodedJWT(String token){
        return JWT.require(Algorithm.HMAC256(secret)).build().verify(token);//若报错 则说明token不合法
    }

}

拦截器使用

public class JWTIntercepeptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String, Object> map = new HashMap<>();
        //获取请求头中的令牌
        String token = request.getHeader("token");
        try {
            JWTUtil.getDDecodedJWT(token);//验证token
            return true;
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msg", "无效签名");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg", "token过期");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg", "token算法不一致");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效");
        }
        map.put("state", false);//设置状态
        //将map转为json
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
    }
}
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTIntercepeptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/**");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值