SpringBoot预检请求跨域问题解决方案

目录

  • 先说结论
  • 问题分析
    • 技术说明
    • 问题出现时情况
    • 问题理解
    • 未解决的问题
  • 参考文章:

先说结论

增加一个过滤器类即可:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    private static final String OPTIONS = "OPTIONS";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST,DELETE,PUT");
        res.addHeader("Access-Control-Allow-Headers", "*");
        res.addHeader("Access-Control-Max-Age", "3600");

        // 如果是OPTIONS则结束请求
        if (OPTIONS.equals(((HttpServletRequest) request).getMethod())) {
            response.getWriter().println("ok");
            return;
        }

        chain.doFilter(request, response);
    }
}

问题分析

技术说明

使用的是SpringBoot构建了一个java后端服务。

问题出现时情况

  1. 已经配置了CORS的configuration,代码如下:
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
                .allowedHeaders("*")
                .maxAge(3600);
    }
}
  1. 对于简单请求,可以直接发送并获取信息,这要归功于CorsConfiguration,没有它简单请求也是跨域的。
  2. 但是当我自行设定了一个header之后,再发出的请求将为跨域请求,浏览器报错信息为:Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.,说的很明确了,响应缺少一个运行该源的头。
  3. 对于简单请求,响应头部有Access-Control-Allow-Origin的属性。

问题理解

  1. 网上很多都在说明什么是跨域请求,怎么个流程,这里就不再赘述了。
  2. 需要说明的是,复杂请求会先发送的这个预检请求的方法是OPTIONS,但是及时在CorsConfiguration中allowedMethods中添加该方法依然无济于事。那么此时我们应该对这个预检请求进行单独处理。
  3. 此时即有了问题结论中的过滤器类,并且我们将其声明为最高等级,遇到了OPTIONS方法直接返回并携带对应的头部。

未解决的问题

这里其实有一个很奇怪的现象,在我的这个后端实现中,对于/user路径下的接口,并不需要额外的配置即可获取复杂请求并响应,一旦不在/user路径下,相同的前端请求,相同的后端配置,就会发生跨域,这一点暂时还没有得到清晰的解决。
在添加了filter之后,所有的请求均可以正常响应了。

参考文章:

  1. SpringBoot跨域&预请求

你可能感兴趣的:(Debug,spring,boot,java,spring,跨域,CORS)