JWT令牌使用及验证
前言
环境版本号
springboot 3.1.3
java 17
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络上以JSON对象的形式安全地传输信息。JWT可以由两方之间轻松传递,因为它是经过数字签名的,因此可以被验证和信任。JWT通常用于身份验证和信息交换,特别是在前后端分离的应用中。
JWT的结构
JWT由三部分组成:
1.Header(头部):头部通常由两部分组成,alg表示使用的算法(例如,HMAC SHA256或RSA),typ表示令牌的类型,JWT标准规定为"JWT"。
2.Payload(负载):负载包含声明,声明是关于实体(通常是用户)和其他数据的声明。有三种类型的声明:注册声明、公共声明和私有声明。
3.Signature(签名):为了创建签名部分,需要使用编码过的头部、编码过的负载,以及一个密钥(secret)。这个签名用于验证消息在传递过程中没有被篡改。
使用步骤
1.步骤
pom.xml代码如下:
<!--java-jwt坐标-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
2.步骤
utils/JwtUtil代码如下:
package com.dong.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtil {
//配置密钥为dong
private static final String KEY = "dong";
//接收业务数据,生成token并返回
public static String genToken(Map<String, Object> claims) {
return JWT.create()
.withClaim("claims", claims)//添加载荷
.withExpiresAt(new Date(System.currentTimeMillis() + 1000*60*60*24))//添加过期时间一天
.sign(Algorithm.HMAC256(KEY));//指定算法,配置秘钥dong
}
//接收token,验证token,并返回业务数据
public static Map<String, Object> parseToken(String token) {
return JWT.require(Algorithm.HMAC256(KEY))
.build()
.verify(token)
.getClaim("claims")
.asMap();
}
}
3.步骤
controller/UserController代码如下:
@PostMapping("/login")
public Result<String> login(@Pattern(regexp = "^\\S{5,16}$",message = "用户名长度必须在5到16位之间") String username,
@Pattern(regexp = "^\\S{5,16}$",message = "密码长度必须在5到16位之间") String password) {
//根据用户名查询用户
User loginUser = userService.findByUserName(username);
//判断该用户是否存在
if (loginUser == null) {
return Result.error("用户名错误");
}
//判断密码是否正确 loginUser对象中的password是密文,对比加密后的密码是否相等
if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
//登录成功后,使用id和用户名生成jwt令牌
Map<String, Object> claims = new HashMap<>();
claims.put("id", loginUser.getId());
claims.put("username", loginUser.getUsername());
String token = JwtUtil.genToken(claims);
return Result.success(token);//返回jwt令牌
}
return Result.error("密码错误");
}
}
4.步骤
controller/ArticleController代码如下:
@RestController
@RequestMapping("/article")
public class ArticleController {
@GetMapping("/list")
public Result<String> List(@RequestHeader(name = "Authorization") String token, HttpServletResponse response){
//验证token,查看是否持有jwt令牌
try {
Map<String, Object> claims = JwtUtil.parseToken(token);
return Result.success("展示所有文章内容");
} catch (Exception e) {
//访问失败返回异常
//设置http响应状态码为401
response.setStatus(401);
return Result.error("未登录");
}
}
}
总结
JWT与Session的比较
1、轻量且无状态: JWT是轻量级的,信息以JSON格式存储,使其易于在网络上传输。与传统的基于Session的认证相比,JWT不需要在服务器上保存会话状态,使其无状态。这意味着每个请求都包含了身份验证信息,服务器无需在存储和管理会话状态。
2、跨域: JWT可以在跨域情况下安全地传递信息,因为它可以在请求头中传递,并且不受同源策略的限制。
3、可扩展性: JWT的负载部分可以包含任意数量的声明,这使得它非常灵活,可以用于各种场景,如身份验证、授权和信息交换。
4、分布式系统支持: 在微服务和分布式系统中,JWT是一种方便的方式来管理用户身份验证,因为它不需要在各个服务之间共享会话状态。
5、可靠性: 由于JWT使用签名进行验证,可以确保信息的完整性和来源。这降低了被篡改的风险。
6、适用于移动应用: 与使用Session的传统Web应用相比,JWT对于移动应用更为友好,因为它可以轻松地集成到移动应用的请求头中。