前言

做前后端分离项目的时候,在前端页面测试接口时遇到的一个报错:

1
Access to XMLHttpRequest at 'http://localhost:7777/article/hotArticleList' from origin 'http://localhost:8080' 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.
之后上百度查了查发现是跨域的问题,那么就有了这篇文章。

什么是跨域?

跨域是指从 一个域名的网页 去请求 另一个域名的资源。比如从百度(baidu.com)页面去请求我博客(heyzqf.com)的资源,由于有同源策略的关系,一般是不允许这么直接访问的

什么是同源策略?

同源策略是浏览器中一个非常重要的安全策略,它的作用是限制不同源之间的交互,从而有效避免一些浏览器层面的攻击。不同源之间的请求是无法交互的,必须符合同源策略的请求才能进行访问。

什么是同源:

  • 协议、域名、端口都相同

    URL1 URL2 说明 是否同源
    http://localhost:4000/archives/ http://localhost:4000/tags/ 协议、域名、端口均相同 同源
    http://localhost:4000/archives/ https://localhost:4000/tags/ 协议不同,域名和端口相同 不同源
    http://heyzqf.com/archives/ http://localhost:4000/tags/ 域名不同,协议和端口相同 不同源
    http://localhost:8080/archives/ http://localhost:7777/tags/ 端口不同,域名和协议相同 不同源

为什么要跨域?

在一些情况下,我们是需要跨域访问的。比如,程序员开发网站的时候,就有可能需要在本地访问服务器的数据。再比如某公司的A页面(a.app.com)需要获取B页面(b.app.com)。

解决方法

使用 CORS 策略可以了。

CORS: Cross Origin Resource Sharing(跨域资源共享)

在 Spring Boot项目 中解决跨域问题的三种方案:

  • 方案一:在目标方法上添加 @CrossOrigin注解

    1
    2
    3
    4
    5
    6
    7
    8
    @CrossOrigin // 跨域注解
    @GetMapping("/hotArticleList")
    public ResponseResult hotArticleList(){
    //查询热门文章,封装成ResponseResult返回
    ResponseResult result = articleService.hotArticleList();

    return result;
    }

  • 方案二:添加 CORS 过滤器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Configuration // 配置类注解
    public class CorsConfig {

    @Bean // 注入Spring容器
    // (org.springframework.web.filter.CorsFilter)
    public CorsFilter corsFilter(){
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    // 允许哪些域访问
    corsConfiguration.addAllowedOrigin("*");
    // 请求的头字段
    corsConfiguration.addAllowedHeader("*");
    // 请求的方式
    corsConfiguration.addAllowedMethod("*");

    // (org.springframework.web.cors.UrlBasedCorsConfigurationSource)
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    // 映射路径
    source.registerCorsConfiguration("/**", corsConfiguration);

    return new CorsFilter(source);
    }

    }

  • 方案三:实现 WebMvcConfigurer 接口, 重写 addCorsMappings 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Configuration
    public class WebConfig implements WebMvcConfigurer{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    // 设置允许跨域的路径, 映射
    registry.addMapping("/**")
    // 设置允许跨域请求的域名
    .allowedOriginPatterns("*")
    // 设置允许的请求方式
    .allowedMethods("GET", "POST", "DELETE", "PUT", "HEAD", "OPTIONS")
    // 是否允许cookie
    .allowCredentials(true)
    // 设置允许的header属性
    .allowedHeaders("*")
    // 跨域允许时间, 3600秒内浏览器不再询问,有效期
    .maxAge(3600);
    }

    }

参考链接