springboot整合jwt和基础用法
springboot整合jwt和基础用法
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zuke</groupId>
<artifactId>springboot-jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-jwt</name>
<description>springboot-jwt</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- jdk1.8以上需要加入依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- jwt依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- web开发包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
src/main/resources/application.yml
server:
port: 8802
实体类
src/main/java/com/zuke/springbootjwt/entity/User.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zukedog@163.com
* @date 2024/8/4 12:54
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private String password;
private String token;
}
jwt工具类(按需修改)
src/main/java/com/zuke/springbootjwt/utils/JwtUtils.java
public class JwtUtil {
/**
* 生成JWT
* @param username 用户名
* @param role 用户角色
* @param validTime JWT有效期(毫秒)
* @param signature 签名密钥
* @return 生成的JWT字符串
*/
public static String generateToken(String username, String role, long validTime, String signature) {
JwtBuilder jwtBuilder = Jwts.builder();
String token = jwtBuilder
// Header
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
// Payload
.claim("username", username)
.claim("role", role)
.setExpiration(new Date(System.currentTimeMillis() + validTime))
.setId(UUID.randomUUID().toString())
// Signature
.signWith(SignatureAlgorithm.HS256, signature)
.compact();
return token;
}
/**
* 校验并解析JWT
* @param token JWT字符串
* @param signature 签名密钥
* @return 解析后的Claims对象,如果校验失败则返回null
*/
public static TokenValidationResult checkToken(String token, String signature) {
if (StringUtils.isEmpty(token) || StringUtils.isEmpty(signature)) {
return new TokenValidationResult(false, TokenValidationError.INVALID_TOKEN);
}
try {
Claims claims = Jwts.parser()
.setSigningKey(signature)
.parseClaimsJws(token)
.getBody();
return new TokenValidationResult(true, TokenValidationError.INVALID_TOKEN);
} catch (ExpiredJwtException e) {
// 令牌已过期
return new TokenValidationResult(false, TokenValidationError.EXPIRED_TOKEN);
} catch (SignatureException e) {
// 签名验证失败
return new TokenValidationResult(false, TokenValidationError.INVALID_SIGNATURE);
} catch (MalformedJwtException e) {
// 令牌构造不正确
return new TokenValidationResult(false, TokenValidationError.MALFORMED_TOKEN);
} catch (JwtException e) {
// 其他JWT相关异常
return new TokenValidationResult(false, TokenValidationError.INVALID_TOKEN);
}
}
/**
* 更新token的过期时间为1小时
* @param oldToken 原始token
* @param signature 签名密钥
* @return 更新后的token,如果原token无效则返回null
*/
public static String updateTokenExpiration(String oldToken, String signature) {
if (StringUtils.isEmpty(oldToken) || StringUtils.isEmpty(signature)) {
return null;
}
try {
// 解析原token
Claims claims = Jwts.parser()
.setSigningKey(signature)
.parseClaimsJws(oldToken)
.getBody();
// 获取原token中的信息
String username = claims.get("username", String.class);
String role = claims.get("role", String.class);
// 生成新token,有效期为1小时
long validTime = 1000 * 60 * 60; // 1小时
return generateToken(username, role, validTime, signature);
} catch (JwtException e) {
// JWT解析失败
e.printStackTrace();
return null;
}
}
/**
* 验证token中的角色类型是否在允许的角色类型列表中
* @param token JWT字符串
* @param signature 签名密钥
* @param roleTypes 允许的角色类型数组
* @throws JwtException 当token无效或角色类型不匹配时抛出
* @throws IllegalArgumentException 当参数为空时抛出
*/
public static void validateTokenRole(String token, String signature, String[] roleTypes) {
// 参数校验
if (StringUtils.isEmpty(token) || StringUtils.isEmpty(signature) || roleTypes == null || roleTypes.length == 0) {
throw new IllegalArgumentException("Token, signature and roleTypes cannot be null or empty");
}
try {
// 解析token
Claims claims = Jwts.parser()
.setSigningKey(signature)
.parseClaimsJws(token)
.getBody();
// 获取token中的角色
String tokenRole = claims.get("role", String.class);
if (StringUtils.isEmpty(tokenRole)) {
throw new JwtException("Token does not contain role information");
}
// 检查角色是否在允许的列表中
boolean roleMatched = false;
for (String allowedRole : roleTypes) {
if (tokenRole.equals(allowedRole)) {
roleMatched = true;
break;
}
}
// 如果角色不匹配,抛出异常
if (!roleMatched) {
throw new CustomException("此操作不允许使用此用户角色");
}
} catch (JwtException e) {
throw new CustomException(e.getMessage());
}
}
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(Constant.JWT_SIGNATURE)
.parseClaimsJws(token)
.getBody();
}
}
配置允许跨域
src/main/java/com/zuke/springbootjwt/config/CrosConfiguration.java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author zukedog@163.com
* @date 2024/8/4 13:45
*/
@Configuration
public class CrosConfiguration implements WebMvcConfigurer {
//解决跨域问题
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
测试接口
src/main/java/com/zuke/springbootjwt/controller/UserController.java
import com.zuke.springbootjwt.entity.User;
import com.zuke.springbootjwt.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author zukedog@163.com
* @date 2024/8/4 12:55
*/
@RestController
public class UserController {
//模拟数据库密码
private final String USERNAME = "root";
private final String PASSWORD = "root";
private final String SIGNATURE = "root";
@PostMapping("/login")
public String login(@RequestBody User user) {
if (USERNAME.equals(user.getUsername()) && PASSWORD.equals(user.getPassword())){
//添加token
return JwtUtils.generateToken(user.getUsername(),"user",1000*60*60,SIGNATURE);
}
return null;
}
@GetMapping("/checkToken")
public boolean checkToken(HttpServletRequest request){
String token = request.getHeader("token");
return JwtUtils.checkToken(token,SIGNATURE);
}
}
分类:
标签:
SpringBoot Jwt 令牌
版权申明
本文系作者 @卸了磨的驴 原创发布在springboot整合jwt和基础用法。未经许可,禁止转载。
全部评论