啊这, 拦截器和跨域冲突了

216 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

前言

一直想写一个博客项目, 这不最近在学习前端嘛, 好不容易会前端给后端发送接口请求了, 结果一直报跨域错误, 当天解决了三四个小时, 第二天解决了一小时, 接下来就总结一下解决跨域问题的几个方法

我是java选手, 使用的框架是SpringBoot

跨域问题的产生与解决

浏览器要遵循同源策略, 不同源那就是跨域了

同源策略:
请求的 协议 域名 端口 全部保持一致

那么我们知道了问题产生的原因, 该怎么解决呢, 主要分为三个方面
前端:

  • jsonp
  • nodejs中间件代理跨域 后端:
  • 继承WebMvcConfigurationSupport或者WebMvcConfigurer类, 实现addCorsMappings方法
  • 在允许跨域的方法上添加@CrossOrigin注解
  • 重写corFilter方法 服务器端:
  • Nginx反向代理

在这里我主要讲解后端和Nginx的实现方法, 前端的, 我不会.....

重写 addCorsMappings() 方法

// 继承这两种类都可以 
@Configuration
//public class WebMvcConfig implements WebMvcConfigurationSupport {
public class WebMvcConfig implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //放行哪些原始域
                .allowedOrigins("*")
                // 允许哪些请求
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                // 是否放行所有 header
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

重写 corsFilter() 方法

@Configuration
public class GlobalCorsConfig {
 
    @Bean
    public CorsFilter corsFilter() {
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        // 放行哪些原始网站域名
        config.addAllowedOrigin("http://localhost:8080");
        // 是否允许发送 Cookie
        config.setAllowCredentials(true);
        //放行哪些请求方式
        config.addAllowedMethod("*");
        //放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }
}

Nginx允许跨域

add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
        return 204;
}

具体如下图所示 image.png

拦截器与跨域冲突

在开发过程中碰到过明明重写了addCorsMappings()方法, 但是跨域还是没有起作用, 这种情况下很有可能是你开启了拦截器

image.png

idea中双击Shift搜索一下addInterceptors()方法, 看是否有实现拦截器功能

原因是因为接口请求在刚发送到后端时是先被自定义拦截器给拦截到了, 如果拦截器证明了没有问题才会开始执行跨域配置, 这个时候有两种方案

    1. 实现corFilter方法, 上面有讲过
    1. 在拦截器中首行添加如下代码(网上收集, 未尝试)
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
    return true;
}

后端配置了跨域, 走Nginx还是报跨域问题

image.png

我目前项目中是由拦截器的, 所以我写了corsFilter方法, 按理来讲是能够通过跨域的, 但是, 谁知道跨域再次失败

image.png

后来多次实验发现, 是因为我后端代码和Nginx都写入了跨域配置, 导致第一次跨域访问成功, 第二次访问显示跨域问题

image.png

小知识

前端存储token的时候, 不是要自定义key嘛, 这个自定义的key不要有下划线, 用-, 只能说才过坑两小时, 真的栓Q




本文内容到此结束了

如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。

如有错误❌疑问💬欢迎各位大佬指出。

我是 宁轩 , 我们下次再见