Java使用JWT

本文深入解析JWT(JsonWebToken)的原理,包括其结构(Header, Payload, Signature)和使用场景。阐述了JWT在授权和信息交换中的作用,并对比了传统Session认证的优缺点。此外,通过示例展示了JWT的生成与验证过程,以及在SpringBoot项目中的应用。最后,讨论了JWT认证中可能出现的异常情况及其处理。

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

本文学习了网络上的视频资源 此处

什么是JWT(Json Web Token)?

在这里插入图片描述
一种规范、思想

JSON Web令牌

官方解释

JSON Web Token (JWT) 是一个开放标准 ( RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息。该信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

什么时候应该使用 ?

  • 授权
  • 信息交换

为什么要使用JWT认证

传统的Session认证

认证方式 我们向服务器发送请求 为了应用能识别是哪个用户发出的请求,我们只能在服务器端存储一份用户的登录信息,会再响应时传递给浏览器,让其保存为cookie,以便下次请求时发送给我们的应用。就可以识别出哪个用户了。 请求应用携带cookie找到对应的session。

传统session示例

创建一个springboot项目
在这里插入图片描述
创建一个controller 模拟放入session情况

/**
 * @create: 2021/8/25
 * @author: Tony Stark
 */
@RestController
public class TestController {
    @GetMapping("/test/test")
    private String test(String username, HttpServletRequest request){
        //校验成功之后  把用户信息放到session中
        request.getSession().setAttribute("username",username);
         return "login ok!";
    }
}

那么传统的session认证有什么问题呢?

每个用户认证之后,服务端都会做一次记录,通常我们的session都是保存在内存中的,认证的用户越多,服务端的压力就会增大。

我们认证之后,认证的记录被保存在内存中时,意味着下次用户要验证成功还要访问这台服务器,如果是分布式应用就限制了相应的能力

如果我们的cookie被获取了是很危险的

JWT认证简单流程

1.前端通过Web表单将自己的用户名和密码发送到后端接口 POST请求

2.后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload负载 对其进行编码之后形成JWT(Token)

3.后端将JWT字符串作为返回值返回给前端,前端将返回的结果保存 ,退出登录时删除即可

5.前端每次请求时将JWT放入HTTP Header 头中的Authorization 授权位中

6.后端检查是否存在 , 正确性 。

7.验证通过后后端使用JWT中包含的用户信息进行操作,返回结果。

JWT结构

1.标头(header)

2.有效载荷(Payload)

3.签名(Singnature)

通常形式 header.Payload.Signature

1.header

两部分组成 : 令牌类型(JWT)和所使用的签名算法,例如HMAC、、、等 会使用Base64编码组成JWT第一部分。 默认值就是下列值 一般我们不做修改

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

2.payload

有效负载,其中包含声明 ,声明是用户和其他数据的声明。也会使用base64编码,官方建议不要放敏感信息,密码等等、、

{
    "name": "Tom",
    "admin":"root"
}

3.Singnature签名

签名需要使用前两部分base64编码后的密文+一个密钥 用header中指定的算法进行签名,用于保证JWT没被篡改过。

使用JWT
第一步 引入jwt依赖

<!--引入JWT依赖-->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>

获取签名

编写测试类

@Test
void testJwtCreate() {
    Calendar instance = Calendar.getInstance();
    instance.add(Calendar.SECOND, 5);
    String token = JWT.create()
            //头可以不指定一般用默认值
            .withClaim("username", "张三")//payLoad
            .withClaim("userId", 1)
            .withExpiresAt(instance.getTime()) //指定令牌的过期时间
            .sign(Algorithm.HMAC256("qweqwrpf1")); // Singnature
         //Algorithm.ECDSA256()使用哪种加密算法  括号中写自己指定的密钥

    System.out.println(token);
}

输出结果

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2Mjk5NDMwNDgsInVzZXJJZCI6MSwidXNlcm5hbWUiOiLlvKDkuIkifQ.tEu5AI2-XDrHy5X7xyTthAOJVPg_GaU5q2-yViDq-7c

验证签名

@Test
    public void testRequire() {
        //require  解密    传入加密的签名
        //创建验证对象
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("qweqwrpf1")).build();
        //使用验证对象中的验证方法  传入生成的JWT串  会返回一个解码的JWT
        DecodedJWT decodedJWT = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2Mjk5NDcxNzQsInVzZXJJZCI6MSwidXNlcm5hbWUiOiLlvKDkuIkifQ.qZQwSXhf6omVuAOPGy1DFrOHR5NMF9nYaFIoS1qLgt4");
        //获取解码之后的数据信息
        System.out.println(decodedJWT.getPayload());
        System.out.println("userId为 : "+decodedJWT.getClaim("userId").asInt());
        System.out.println(decodedJWT.getClaims());
        //获取过期时间
        System.out.println("过期时间为 : "+decodedJWT.getExpiresAt());
    }

输出

eyJleHAiOjE2Mjk5NDcxNzQsInVzZXJJZCI6MSwidXNlcm5hbWUiOiLlvKDkuIkifQ
userId为 : 1
{exp=com.auth0.jwt.impl.JsonNodeClaim@67080771, userId=com.auth0.jwt.impl.JsonNodeClaim@72cde7cc, username=com.auth0.jwt.impl.JsonNodeClaim@5fd4f8f5}
过期时间为 : Thu Aug 26 11:06:14 CST 2021

几种异常判断

解码会先判断算法如果算法不一致会抛出异常

com.auth0.jwt.exceptions.AlgorithmMismatchException

签名不一致

SignatureVerificationException

签名过期异常

TokenExpiredException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值