美文网首页
跨域问题解决

跨域问题解决

作者: 高节 | 来源:发表于2022-11-03 11:30 被阅读0次

1.背景

今天给自己的demo (SpringBoot + Vue) 加了个请求头,也就是前端直接传过来,然后后台统一获取,想着这样更优雅,所以是用的拦截器实现,然后就导致后台默认的跨域配置失效,前端报了跨域问题(在浏览器控制台)

2.出现错误

2.1.响应码问题

Access to XMLHttpRequest at 'http://localhost:8001/memo/user/info' from origin 'http://localhost:9528' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

后台报错:拦截器 preHandle 抛异常,正是抛异常的地方
浏览器网络报错:响应码为500
浏览器控制台报错:控制台报错 It does not have HTTP ok status

2.1.原因分析

基础知识!

对于浏览器的请求,浏览器会根据自己的判断分为2种,一种是简单请求,另一种是非简单请求,对于非简单请求,浏览器会先发送一个OPTIONS请求(是不会带参数的),返回成功之后再发送原本的请求

由于配置了拦截器,当OPTIONS请求走到拦截器逻辑时,由于没有带参数,所以抛出了异常,这样就没有返回成功 http 状态码,所以原本的POST请求就不会发出

2.2.响应头缺少问题

Access to XMLHttpRequest at 'http://localhost:8001/memo/user/login' from origin 'http://localhost:9528' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

后台代码:由于之前是OPTIONS请求返回500,所以想着在Filter将请求返回成功,所以OPTIONS问题解决了
浏览器网络报错:由于 Filter 直接给 OPTIONS 返回成功,所以现在请求卡在了原本的请求
浏览器控制台报错:跨域问题,缺少响应头 No 'Access-Control-Allow-Origin' header is present on the requested resource.

2.2.原因分析

虽然解决了OPTIONS问题,但是在实际请求处理的时候,由于在Interceptor 处理逻辑抛出异常,导致了跨域的处理逻辑没有执行,所以响应头缺少信息,浏览器就报错了

3.解决方案

3.1.原本的跨域配置

这种配置在没有自定义拦截器的时候没问题,但是有了拦截器之后,如果拦截器中出现异常,就可能导致
① OPTIONS 请求返回失败
② 跨域处理不执行,响应缺少跨域的头,浏览器就会报错

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET","POST","HEAD","PUT","DELETE")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

3.2.最终的配置

使用 Filter 的方式做跨域,因为 Filter 的执行是在 interceptor 的外层
① 所以即使 Interceptor 里面抛异常,也不会影响 Filter 的跨域处理,照样会执行
② 而且由于 Filter 处理逻辑会早于 Interceptor 执行,上述方法会直接将 OPTIONS 请求直接返回,所以不会再出现 OPTIONS 请求失败的情况

    /**
     * 跨域处理
     * 因为 WebMvcConfigurer 自带的跨域配置,在有拦截器的情况下,有可能执行不到
     * 所以使用 Filter 的方式,比拦截器先执行,不会受拦截器影响
     */
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.addExposedHeader("token");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }

相关文章

网友评论

      本文标题:跨域问题解决

      本文链接:https://www.haomeiwen.com/subject/lwnstdtx.html