1.生成token与解析token部分代码
pom
<!-- token验证 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
jwt token工具类(使用的话createToken的参数与方法体与getTokenRes的返回值需要自己看着修改)
- withAudience()可以放用户名、账户id之类的,这样就不用查询数据库了
- withExpiresAt()放token的过期时间,上面的表示token24小时之后过期
- sign()放签名认证,一般是放加密后的密码
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component("Token")
public class Token {
/**
* toekn 密钥
*/
private static final String JWT_SECRET = "qiesiyv";//自己随便起个字符串
/**
* token 过期时间
*/
private static final int calendarField = Calendar.DATE;
private static final int calendarInterval = 30;
private static final Algorithm algorithm = Algorithm.HMAC256(JWT_SECRET);
// header Map
private static final Map<String, Object> map = new HashMap<>();
private static JWTCreator.Builder createTokenBuilder() {
/** 加密方式 **/
map.put("alg", "HS256");
map.put("typ", "JWT");
// 签发时间
Date iaDate = new Date();
// 设置过期时间
Calendar nowTime = Calendar.getInstance();
nowTime.add(calendarField, calendarInterval);//前者为时间单位,后者时间数量
Date expiresDate = nowTime.getTime();
JWTCreator.Builder builder = JWT.create().withHeader(map)
.withIssuedAt(iaDate)
.withExpiresAt(expiresDate)
.withClaim("iss", "qiesiyv") //payload iss jwt的签发者 看着起名
.withClaim("aud", "app"); //aud 接收的乙方 看着起名
return builder;
}
/**
* 生成token
*
* @param
* @return
*/
public static String createToken(String uid,String userimg,String username,String userbimg) {//token保存的数据
JWTCreator.Builder builder = createTokenBuilder();
String token = builder.withClaim("uid", uid)
.withClaim("userimg", userimg)
.withClaim("username", username)
.withClaim("userbimg", userbimg)
.sign(algorithm);
return token;
}
// 解析
static DecodedJWT verifyToken(String token) {
DecodedJWT jwt = null;
try {
//解析方式和密钥
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = JWT.decode(token);
jwt = verifier.verify(decodedJWT);
} catch (Exception e) {
e.printStackTrace();
// token 校检失败
}
return jwt;
}
/**
* 解析token获取内容
* @param token
* @return
*/
public static TokenRes getTokenRes(String token) {
DecodedJWT jwt = verifyToken(token);
Map<String, Claim> claimMap = jwt.getClaims();
String uid = claimMap.get("uid").asString();//赋值返回值
String userimg = claimMap.get("userimg").asString();
String username = claimMap.get("username").asString();
String userbimg = claimMap.get("userbimg").asString();
TokenRes res = new TokenRes(uid,userimg,username,userbimg);
return res;
}
}
返回值类演示
@Data
@AllArgsConstructor
public class TokenRes {
private String uid;//用户id
private String userimg;//用户头像
private String username;//用户名
private String userbimg;//用户主页图
}
2.拦截规则
拦截工具类
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
System.out.println(token);
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
if (StringUtils.isBlank(token)) {
throw new RuntimeException("无token,请重新登录");
}
// 验证 token
try {
if(Token.verifyToken(token)==null)
throw new RuntimeException("token无效");
System.out.println("token校验");
} catch (JWTVerificationException e) {
throw new RuntimeException("token失效,请重新登录");
}
return true;
}
}
拦截配置类
- addPathPatterns() 要拦截的接口
- excludePathPatterns()开放的接口
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Description: 拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public JwtInterceptor jwtInterceptor(){
return new JwtInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/ceshi/ceshi","/**/import");
}
}
补充:拿取拦截方法的注解值(以自定义RepeatSubmit示例)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatSubmit {
/**
* 默认失效时间5秒
*/
long seconds() default 5;
}
取值
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod){
//只拦截标注了@RepeatSubmit该注解
HandlerMethod method=(HandlerMethod)handler;
//标注在方法上的@RepeatSubmit
RepeatSubmit repeatSubmitByMethod =
AnnotationUtils.findAnnotation(method.getMethod(),RepeatSubmit.class);
//标注在controler类上的@RepeatSubmit
RepeatSubmit repeatSubmitByCls =
AnnotationUtils.findAnnotation(method.getMethod().getDeclaringClass(), RepeatSubmit.class);
//没有限制重复提交,直接跳过
if (Objects.isNull(repeatSubmitByMethod)&&Objects.isNull(repeatSubmitByCls))
return true;
//取值方法//repeatSubmitByMethod.seconds()//repeatSubmitByCls.seconds()
}
}