问题复现
我的项目是前后端分离的项目,后端配置了跨域以及拦截器
跨域代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private JwtFilter jwtFilter;
/**
* 不需要拦截地址
*/
public static final String[] EXCLUDE_URLS = {
"/userLogin/**",
"/webjars/**",
"/swagger-ui.html/**",
"/swagger-resources/**",
"/swagger-ui.html/**",
"/favicon.ico",
"/error",
"/null/**",
"/ws"
};
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtFilter)
.addPathPatterns("/**")
.excludePathPatterns(EXCLUDE_URLS);
}
}
拦截器
@Slf4j
@Component
public class JwtFilter extends HandlerInterceptorAdapter {
@Resource
JwtTokenUtil jwtTokenUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("request.getRequestURI() = " + request.getRequestURI());
//如果是OPTIONS请求的话 进行直接放行
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())){
System.out.println("OPTIONS请求放行");
return true;
}
// 获取token
String token = request.getHeader(jwtTokenUtil.header);
if (StringUtils.isEmpty(token)) {
token = request.getParameter(jwtTokenUtil.header);
}
if (StringUtils.isEmpty(token)) {
// 这里直接返回false,
log.error("token 不能为空!");
return false;
}
// 判断token是否超时
if (jwtTokenUtil.isTokenExpired(token)) {
log.error("token 已失效!");
return false;
}
// 判断 token 是否已在黑名单
if (jwtTokenUtil.checkBlacklist(token)) {
log.error("token 已被加入黑名单!");
return false;
}
// 获取用户信息
UserTokenInfo userInfoToken = jwtTokenUtil.getUserInfoToken(token);
// 通过用户信息去判断用户状态,等业务
if (null != userInfoToken.getId()){
UserContext.setUser(userInfoToken.getId());
}
return true;
}
}
问题分析
前端的发送的过程实际上发送了两次请求,第一次为OPTIONS请求,第二次才GET/POST等请求
在OPTIONS请求中,不会携带请求头的参数,所以在拦截器上获取请求头为空,自定义的拦截器拦截成功:第一次请求不能通过,就不能获取第二次的请求了GET/POST
解决方法
在拦截器上放行第一次的OPTIONS请求即可。
@Slf4j
@Component
public class JwtFilter extends HandlerInterceptorAdapter {
@Resource
JwtTokenUtil jwtTokenUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("request.getRequestURI() = " + request.getRequestURI());
//如果是OPTIONS请求的话 进行直接放行
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())){
System.out.println("OPTIONS请求放行");
return true;
}
// 获取token
String token = request.getHeader(jwtTokenUtil.header);
if (StringUtils.isEmpty(token)) {
token = request.getParameter(jwtTokenUtil.header);
}
if (StringUtils.isEmpty(token)) {
// 这里直接返回false,
log.error("token 不能为空!");
return false;
}
// 判断token是否超时
if (jwtTokenUtil.isTokenExpired(token)) {
log.error("token 已失效!");
return false;
}
// 判断 token 是否已在黑名单
if (jwtTokenUtil.checkBlacklist(token)) {
log.error("token 已被加入黑名单!");
return false;
}
// 获取用户信息
UserTokenInfo userInfoToken = jwtTokenUtil.getUserInfoToken(token);
// 通过用户信息去判断用户状态,等业务
if (null != userInfoToken.getId()){
UserContext.setUser(userInfoToken.getId());
}
return true;
}
}
标签:拦截器,return,跨域,jwtTokenUtil,request,public,token,OPTIONS,仍会
From: https://blog.csdn.net/qq_63431773/article/details/136962060