1、安装依赖
在pom.xml中添加一下三个依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
2、application.yml配置
jwt.secret:JWT 密钥,用于对 JWT 进行签名和解密。
jwt.expire:JWT 的过期时间,以秒为单位。超过该时间,JWT 将被视为无效。
jwt.header:JWT 在请求头中的字段名称。
config:
jwt:
secret: hge_any_code
expire: 30
header: token
3、配置JWT
创建config文件夹
JwtConfig.java
import java.util.Date;
import io.jsonwebtoken.*;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "config.jwt", ignoreInvalidFields = true)
@Component
@Data
public class JwtConfig {
private String secret;
private Long expire;
private String header;
// 创建token值
//setHeaderParam("typ", "JWT"):设置 JWT token 的头部参数,标识该 token 类型为 JWT。
//setSubject(subject):设置 JWT token 的主题,即 sub 声明。
//setIssuedAt(nowDate):设置 JWT token 的签发时间,即当前时间。
//setExpiration(expireDate):设置 JWT token 的过期时间,即计算得到的过期日期。
//signWith(SignatureAlgorithm.HS512, secret):使用 HMAC-SHA512 签名算法和密钥对 JWT 进行签名。
public String createToken(String subject) {
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + expire * 1000);
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(subject)
.setIssuedAt(nowDate)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
// 解析JWT并获取其中的声明信息。
public Claims getTokenClaim(String token){
try {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e) {
throw new RuntimeException(e);
} catch (UnsupportedJwtException e) {
throw new RuntimeException(e);
} catch (MalformedJwtException e) {
throw new RuntimeException(e);
} catch (SignatureException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
}
}
// 获取 JWT token 中的subject声明信息。
public String getSubject(String token) {
return getTokenClaim(token).getSubject();
}
}
TokenInterceptor.java
拦截器(Interceptor),用于在请求处理之前对请求进行拦截和处理。它的作用是验证请求中的令牌(token)是否有效,并且排除对登录接口的拦截。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private JwtConfig jwtConfig;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
if(uri.contains("login")){
return true;
}
//处理token
String token = request.getHeader(jwtConfig.getHeader());
if(StringUtils.isEmpty(token)){
token = request.getParameter(jwtConfig.getHeader());
}
if(StringUtils.isEmpty(token)){
//返回401, token不能为空
sendError(response,"token不能为空");
return false;
}
try {
jwtConfig.getTokenClaim(token);
} catch (Exception e) {
// throw new RuntimeException(e);
//返回401. token失效,
sendError(response,"token无效");
return false;
}
return true;
}
private void sendError(HttpServletResponse response,String msg) throws IOException {
response.setStatus(401);
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(msg);
}
}
WebConfig.java
这段代码是一个配置类(WebConfig),用于配置拦截器(TokenInterceptor)的使用。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
}
}
4、简单使用
User.java
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
private String address;
private String email;
private String phone;
private String token;
}
UserController.java
// 用户登录
@PostMapping("/login")
public Result toLogin(@RequestBody User user){
// 查询数据库中是否存在匹配的用户记录,返回一个包含符合条件的用户列表
List<User> list = userMapper.toLogin(user);
// 从用户列表中获取第一个用户记录,假设它就是当前登录的用户。
User currentUser = list.get(0);
// 调用jwtConfig.createToken(currentUser.getUsername())方法创建一个JWT令牌。传入当前登录用户的用户名作为令牌的主题(Subject)
String token = jwtConfig.createToken(currentUser.getUsername());
// 将令牌设置到当前登录用户的token属性中
currentUser.setToken(token);
return Result.success("登录成功",currentUser);
}
参考视频:https://www.bilibili.com/video/BV1wh4y1S7dr?p=42&vd_source=39c0a587ece2e4569d9e272c6181b901
p42