jwt验证问题:拦截器进行验证时,没有得到token都会预检不通过。
预检请求不会带参数,因此拦截器获取请求头的jwt(token)时是为null的,所以预检请求都不会通过,浏览器得到预检不通过,就不会发送正式的请求。
解决方案:添加一个过滤器,在过滤器里处理预检请求(OPTIONS)
方案一:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// 预检请求处理
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,JSONP");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept,Authorization,X-CSRF-TOKEN");
// 是预检请求则设置响应状态并返回
if(request.getMethod().equals(RequestMethod.OPTIONS.name())) {
response.setStatus(HttpStatus.OK.value());
return ;
}
}
chain.doFilter(req, res);
}
方案二:
@Component
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
// 预检请求处理
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpRequest.setCharacterEncoding("UTF-8");
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "*");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with");
filterChain.doFilter(request, response);
}
}
为什么会发送预检请求?
如前后端分离不安全(跨域),因此会发送预检请求来检查是否安全。
一般都是浏览检测到请求跨域时,会自动发起。
OPTIONS请求Access-Control-Max-Age 缓存机制,如下请求缓存生效吗?
- url变化会导致缓存失效,需要重新验证预检的返回值
- 预检不关心post data
- header变化,如果是去掉了自定义的header使得请求变成简单请求,不会发送预检。如果是增加其他的header,是会重新验证Access-Control-Allow-Headers的值。
- cookie变化,只要后端允许发送cookie,cookie值变化不会导致缓存失效。
网友评论