pom.xml中引入依赖
pom.xml
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
配置文件中增加全局变量
application.yml
jwt:
header: "Authorization" #token返回头部
tokenPrefix: "Bearer " #token前缀
secret: "peng123456" #密钥
expireTime: 30 #token有效时间 (分钟) 建议一小时以上
增加jwt
工具类
util/JWTUtil
package com.example.springboot2.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.example.springboot2.exception.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@ConfigurationProperties(prefix = "jwt")
@Slf4j
public class JWTUtils {
//定义token返回头部
public static String header;
//token前缀
public static String tokenPrefix;
//签名密钥
public static String secret;
//有效期
public static long expireTime;
//存进客户端的token的key名
public static final String USER_LOGIN_TOKEN = "USER_LOGIN_TOKEN";
public void setHeader(String header) {
JWTUtils.header = header;
}
public void setTokenPrefix(String tokenPrefix) {
JWTUtils.tokenPrefix = tokenPrefix;
}
public void setSecret(String secret) {
JWTUtils.secret = secret;
}
public void setExpireTime(int expireTimeInt) {
JWTUtils.expireTime = expireTimeInt*1000L*60;
}
/**
* 创建TOKEN
* @param sub
* @return
*/
public static String createToken(String sub){
return tokenPrefix + JWT.create()
.withSubject(sub)
.withExpiresAt(new Date(System.currentTimeMillis() + expireTime))
.sign(Algorithm.HMAC512(secret));
}
/**
* 验证token
* @param token
*/
public static String validateToken(String token){
try {
return JWT.require(Algorithm.HMAC512(secret))
.build()
.verify(token.replace(tokenPrefix, ""))
.getSubject();
} catch (TokenExpiredException e){
throw new JwtException("token不能为空");
} catch (Exception e){
throw new JwtException("token验证失败");
}
}
/**
* 检查token是否需要更新
* @param token
* @return
*/
public static boolean isNeedUpdate(String token){
//获取token过期时间
Date expiresAt = null;
try {
expiresAt = JWT.require(Algorithm.HMAC512(secret))
.build()
.verify(token.replace(tokenPrefix, ""))
.getExpiresAt();
} catch (TokenExpiredException e){
return true;
} catch (Exception e){
throw new JwtException("token已过期,请重新登录");
}
//如果剩余过期时间少于过期时常的一般时 需要更新
return (expiresAt.getTime()-System.currentTimeMillis()) < (expireTime>>1);
}
}
增加自定义jwt异常处理类
exception/JwtException
package com.example.springboot2.exception;
public class JwtException extends RuntimeException {
public JwtException(String errorMsg){
super(errorMsg);
}
}
把自定义jwt异常,增加到全局异常类中
exception/GraceExceptionHandler
package com.example.springboot2.exception;
import com.example.springboot2.util.JSONResult;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class GraceExceptionHandler {
@ExceptionHandler(JwtException.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public JSONResult returnJwtException(JwtException e){
return JSONResult.errorMsg(e.getMessage());
}
}
增加对token的拦截
interceptor/LoginInterceptor
package com.example.springboot2.interceptor;
import com.example.springboot2.util.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
/**
* 拦截请求,访问controller之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
JWTUtils.validateToken(token);
return true;
}
/**
* 请求访问到controller之后,渲染视图之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 请求访问到controller之后,渲染视图之后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
配置类中增加对jwt拦截的处理
package com.example.springboot2.config;
import com.example.springboot2.interceptor.LoginInterceptor;
import com.example.springboot2.interceptor.UserInfoInterceptor;
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;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(loginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login");//开放登录路径
}
}
测试
登录controller
package com.example.springboot2.controller;
import com.example.springboot2.util.JSONResult;
import com.example.springboot2.util.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController()
@RequestMapping("login")
@Slf4j
public class LoginController {
@PostMapping("")
public JSONResult login(@RequestBody Map<String, Object> map){
String username = (String) map.get("username");
String password = (String) map.get("password");
Boolean isAge = map.containsKey("age");
if(map.containsKey("age")){
log.info("aaa"+isAge);
}else{
log.info("bbb"+isAge);
}
if(!(username.equalsIgnoreCase("admin") && password.equalsIgnoreCase("123456"))){
return JSONResult.errorMsg("账号密码错误");
}
String token = JWTUtils.createToken(username.toString());
Map<String,Object> res = new HashMap<>();
res.put("token",token);
return JSONResult.ok(res);
}
}
测试
无token
登录,拿到token
有token