目录
- 一.接口统一前缀设置
- 二.JWT POM依赖
- 三.JWT工具类TokenUtils.java
- 四.拦截器JwtInterceptor.java
- 五.拦截器设置
- 六.设置自定义头配置
一.接口统一前缀设置
1.指定controller统一的接口前缀
2.加自定义拦截器JwtInterceptor,设置拦截规则,指定Login接口放行,不需验证token
import com.example.wenxin.constant.Jwt.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /*** @program: wenxin* @ClassName WebConfig* @description: 指定controller统一的接口前缀* @create: 2024-03-29 15:58* @Version 1.0**/
@Configuration
public class WebConfig implements WebMvcConfigurer {@AutowiredJwtInterceptor jwtInterceptor;@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {// 指定controller统一的接口前缀configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));}// 加自定义拦截器JwtInterceptor,设置拦截规则@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**").excludePathPatterns("/api/user/login");}}
二.JWT POM依赖
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>
三.JWT工具类TokenUtils.java
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.wenxin.entity.User;
import com.example.wenxin.service.UserService;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import java.util.Date;/*** @program: wenxin* @ClassName TokenUtils* @description:* @author: XZY* @create: 2024-03-29 16:01* @Version 1.0**/
@Component
@Slf4j
public class TokenUtils {@Autowiredprivate UserService adminService;public static TokenUtils tokenUtils;@PostConstructpublic void init() {tokenUtils = this;tokenUtils.adminService = this.adminService;}/*** 生成token** @return*/public static String genToken(String adminId, String sign) {return JWT.create().withAudience(adminId) // 将 user id 保存到 token 里面,作为载荷.withAudience("999").withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期.sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥}/*** 获取当前登录的用户信息** @return user对象* /admin?token=xxxx*/public static User getCurrentAdmin() {String token = null;try {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();// 将RequestAttributes对象设置为子线程共享
// ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// RequestContextHolder.setRequestAttributes(sra, true);
// HttpServletRequest request = sra.getRequest();token = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}if (StrUtil.isBlank(token)) {log.error("获取当前登录的token失败, token: {}", token);return null;}String adminId = JWT.decode(token).getAudience().get(0);User byId = tokenUtils.adminService.getById(Long.valueOf(adminId));return byId;} catch (Exception e) {log.error("获取当前登录的管理员信息失败, token={}", token, e);return null;}}
}
四.拦截器JwtInterceptor.java
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.wenxin.config.BusException;
import com.example.wenxin.entity.User;
import com.example.wenxin.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; /*** @program: wenxin* @ClassName JwtInterceptor* @description:* @create: 2024-03-29 16:27* @Version 1.0**/
@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {private static final String ERROR_CODE_401 = "401";@Autowiredprivate UserService adminService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}// 执行认证if (StrUtil.isBlank(token)) {throw new BusException(ERROR_CODE_401, "无token,请重新登录");}// 获取 token 中的adminIdString adminId;User user;try {adminId = JWT.decode(token).getAudience().get(0);// 根据token中的userid查询数据库user = adminService.getById(Long.parseLong(adminId));} catch (Exception e) {String errMsg = "token验证失败,请重新登录";log.error(errMsg + ", token=" + token, e);throw new BusException(ERROR_CODE_401, errMsg);}if (user == null) {throw new BusException(ERROR_CODE_401, "用户不存在,请重新登录");}try {// 用户密码加签验证 tokenJWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassWord())).build();jwtVerifier.verify(token); // 验证token} catch (JWTVerificationException e) {throw new BusException(ERROR_CODE_401, "token验证失败,请重新登录");}return true;}
}
五.拦截器设置
请看第一步第二个方法,设置规则
六.设置自定义头配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;/*** @program: wenxin* @ClassName CorsConfig* @description:* @create: 2024-03-29 16:32* @Version 1.0**/
@Configuration
public class CorsConfig {@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置return new CorsFilter(source);}
}
实体类等
/*** @program: wenxin* @ClassName User* @description:* @create: 2024-03-29 16:02* @Version 1.0**/
@Data
public class User {//用户idprivate Long userId;//用户手机号private String userPhone;//用户密码private String passWord;//用户账号private String userName;private String token;
}