一、登录成功后返回token,token里包含用户的基本信息
二、调用其他接口时须带上token
怎么实现的呢?
1、引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.2</version>
</dependency>
2、设置拦截器
package springboot.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import springboot.domain.TUser;
import springboot.exception.AuthException;
import springboot.interceptor.token.PassToken;
import springboot.interceptor.token.TokenConst;
import springboot.util.TokenUtil;
import springboot.util.UserUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
@Slf4j
public class AuthenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) {
log.info("requestUrl:{}", httpServletRequest.getRequestURL().toString());
//判断是否启用token校验
if (!TokenConst.isEnable()) {
log.info("token校验关闭");
return true;
}
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
log.info("不是映射到方法");
return true;
}
// 本地调用跳过直接通过
// String ip = CommonUtil.getIPAddress(httpServletRequest);
// log.info("request-ip:{}", ip);
// if ("127.0.0.1".equals(ip)) {
// log.info("request-ip:{},本地调用跳过验证", ip);
// return true;
// }
//判断类注解
HandlerMethod handlerMethod = (HandlerMethod) object;
Class clazz = handlerMethod.getBeanType();
if (clazz.isAnnotationPresent(PassToken.class)) {
PassToken passToken = (PassToken) clazz.getAnnotation(PassToken.class);
System.out.println(passToken);
if (passToken.required()) {
log.info("检测到类{}配置PassToken,跳过校验", clazz);
return true;
}
}
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
log.info("检测到方法{}配置PassToken,跳过校验", method);
return true;
}
}
// 执行认证
String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
if (StringUtils.isEmpty(token)) {
log.error("token校验失败:token为空");
throw new AuthException("token校验失败:token为空");
}
boolean verified = TokenUtil.verify(token);
if (verified) {
//认证通过,保存当前用户信息到当前线程内存中
TUser user = TokenUtil.getTokenData(token);
UserUtil.setUser(user);
return true;
}
log.error("token校验失败:{}", httpServletRequest.getRequestURL().toString());
throw new AuthException("token校验失败,请尝试重新登录");
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
UserUtil.remove();
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
UserUtil.remove();
}
}
TokenUtil工具类
package springboot.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import springboot.domain.TUser;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
@Slf4j
public class TokenUtil {
//私钥设置(随便乱写的)
private static final String TOKEN_SECRET = "j09Nct83jd5QSmoP1TatrZcqQYd3Iq9ogjT2Ne51Nwp";
//过期时间设置(默认30分钟)
private static long EXPIRE_TIME = 30 * 60 * 1000;
public static boolean verify(String token) {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).build();
try {
jwtVerifier.verify(token);
return true;
} catch (JWTVerificationException e) {
log.error("token校验失败:{}", e.getMessage());
return false;
} catch (Exception e) {
log.error("token校验失败:{}", e.getMessage());
return false;
}
}
public static String getToken(TUser userInfo) {
//过期时间和加密算法设置
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("typ", "JWT");
header.put("alg", "HS256");
return JWT.create()
.withHeader(header)
.withClaim("userName", userInfo.getUsername())
.withExpiresAt(date)
.sign(algorithm);
}
public static TUser getTokenData(String token) {
DecodedJWT jwt = JWT.decode(token);
TUser userInfo = new TUser();
userInfo.setUsername(jwt.getClaim("userName").asString());
userInfo.setPassword(jwt.getClaim("userId").asString());
return userInfo;
}
@Value(value = "${token.expire-ms}")
public void setExpireTime(long expireTime) {
EXPIRE_TIME = expireTime;
log.info("Token超时时间:" + EXPIRE_TIME);
}
}
3、定义拦截器
package springboot.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springboot.interceptor.AuthenInterceptor;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePathPatterns = new ArrayList<>();
excludePathPatterns.add("/error");
excludePathPatterns.add("/swagger-ui.html");
excludePathPatterns.add("/configuration/ui");
excludePathPatterns.add("/swagger-resources/**");
excludePathPatterns.add("/configuration/security");
excludePathPatterns.add("/v2/api-docs");
excludePathPatterns.add("/webjars/**");
excludePathPatterns.add("/**/favicon.ico");
excludePathPatterns.add("/user/login");
excludePathPatterns.add("/user/login1");
excludePathPatterns.add("/user/dispatch");
excludePathPatterns.add("/user/dispatch2");
registry.addInterceptor(new AuthenInterceptor())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns(excludePathPatterns);
}
}
4、登录接口
@PostMapping("/login1")
public ResponseDTO login1(@RequestBody TUser userInfo) {
TUser info = tUserService.getOne(new QueryWrapper<TUser>()
.eq("username", userInfo.getUsername())
.eq("password", userInfo.getPassword()), false);
if (info != null) {
Map<String, String> token = new HashMap<>();
token.put("token", TokenUtil.getToken(info));
return ResponseDTO.success(token);
} else {
return ResponseDTO.failed("用户名或密码错误!");
}
}