除虫计划 跨域预检误拦截

开发时应注意不要拦截 CORS 跨域预检,以避免请求异常。

一、问题

1. 背景

  • SpringBoot 后端系统

  • 后端配置了跨域,使得前后端分离的跨域请求能够正常执行

  • 通过 token 进行校验

    用户登陆后,后台向客户端发送 token,此后客户端每次发送请求都应该在请求头中携带 token

  • 后端配置了拦截器,它将拦截除登录和注册以外的请求,当且仅当请求携带 token 后才放行

2. 问题

前端配置 axios,使得从后端获取了 token 以后,每次请求都携带 token,后端配置了拦截器,对于除登录和注册以外的请求都进行拦截,对 token 进行检查。从逻辑上没有问题,但在实际中某些请求会被拦截。

经检查发现,这类请求:

  • 浏览器控制台报错如下

  • 前端将会同时发送两个同名请求,其中有一个不携带 token 的请求方式为 Options 的请求

二、跨域请求中的预检

具体请看:

前端 跨域请求

简单来说就是:跨域请求中的 “非简单请求”,将会在请求之前进行一次预检,当且仅当预检被正确响应时,正式请求才会发出。

三、问题所在

“预检” 请求的请求头中只携带了对正式请求的描述信息,而没有携带 Token。

当 “预检” 请求被后端的拦截器所拦截时,后端的拦截器无法获取请求中 “理应” 携带的 Token 信息,因此导致 “预检” 请求没有被正确响应,正式请求无法发出。

四、问题解决

在拦截器中放行所有 Options 请求即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
public class AuthHandlerInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
// 放行跨域请求中的预请求
if (request.getMethod().equals("OPTIONS")) {
return true;
}

···

}

}

参考