请求跨域 CORS policy: No ‘Access-Control-Allow-Origin‘

2023-11-11



如在浏览器控制台看到类似于下边的报错,则是出现了跨域请求问题

xxx has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the request resouce

在和前端打交道的时候,经常听到过跨域这个词,安全部门也用XSS这样看起来高大上的名词;

在后端开发中,并没有跨域这么麻烦的东西。所谓的跨域,是对于浏览器来说的,它限制了各种条条框框,以便能够安全的驯服javaScript这只野兽。

所以来吧,看看浏览器为了达到自己的目的,都干了些啥。

1 跨域和同源

所谓的同源,指的是两个URL的 协议(protocal)、域名(host)、端口(port) 都相同的情况,下面给出示例。

对于http://csdn.com/index.html来说,下面展示了4种不同的情况。

【1】https://csdn.com/index.html ---- 协议不同(http与https),所以不同源。

【2】http://csdn.com:8080/index.html ---- 端口不同(80与8080),所以不同源。

【3】http://baidu.com/index.html ---- 域名/主机 不同,所以不同源。

【4】http://csdn.com/home.html ---- 同源。

那么在不同源(跨域)的情况下,js的执行都有哪些限制呢?

【1】存储资源不共享,如Cookie、LocalStorage 和 IndexDB(浏览器数据库)等,都不能相互读取。

【2】跨域的情况下,DOM和Javascript对象都无法获取。

【3】更要命的是,Ajax请求无法发送,限制了前端程序员的发挥。

但随着业务的增长和域名的增加,跨域的需求是越来越多,浏览器的默认行为,成为了这个功能的拦路虎。所以我们需要寻找有效的方法,来突破这条加载自己脖子上的锁套。

下图是一个页面请求多个域名服务器获取资源的情况
在这里插入图片描述

2. CORS 跨域资源共享(解决跨域)

2.1 前端解决(不推荐)

前端工程师,发明了各种各样的请求方法。常见的有:

【1】jsonp 使用javascript的代理模式,动态的创建script标签。比如常见的百度统计代码,虽然不同源,但是你仍然能把信息发送过去。jsonp只能支持GET请求,不支持POST请求。
【2】document.domain + iframe 这个是利用iframe加载主域名相同的资源。
【3】location.hash + iframe 依然是利用iframe等,使用的是全局对象,用起来很绕。
【4】postMessage Html5的新功能,专门用来解决跨域。我们只要发送端拥有某个窗口的有效js的句柄,就可以通过这套机制向该窗口发送任意长度的文本信息。但编程的时候,容易忘掉origin的判断,造成安全问题。

这些方法都需要写很多代码,还容易出错,调试起来也麻烦,所以现在用的最多的,是CORS

这项技术是W3C的标准,前端代码几乎不需要做任何改动,浏览器可以自动完成。听起来非常的魔幻,但它其实是在HTTP协议上做文章的,要在Http的头里面,加入一些附加信息。只要服务器支持,就实现了跨域操作。所以通信的关键就有前端转移到了服务器的配置上。 目前,几乎所有的浏览器都支持。

在这里插入图片描述

2.2 Nginx 解决跨域

对Nginx来说,要解决跨域,就得加一些配置。

location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' true;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' true;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' true;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
}

因为跨域,针对于正常的浏览器限制来说,相当于开了一条特许通道,所以它的配置非常的细腻。

Access-Control-Allow-Origin (最重要),一般设置成 * 一了百了,但它可以指定具体的请求来源,也更加安全。所以,在dev环境调试时,为了方便开发,可以设置成 *,而线上最好设置成具体的domain。

Access-Control-Request-Method ,指定了跨域请求所允许的HTTP方法,我们这里是GET、POST、OPTIONS 等。

Access-Control-Allow-Headers,表明服务器支持的所有头信息字段,用在预检请求中。值得注意的是,一些简单的头部信息,比如Content-Language、Content-Type等,不需要特别声明。如果你想偷懒,可以设置为 * 。


http的交互,是如何执行的呢?

假定当前浏览器访问的网址是http://csdn.com,当发起了一个指向http://baidu.com 的Ajax请求。正常情况下,这是不能通过的。于是浏览器在请求头中,自动添加了一行。

Origin: http://csdn.com

http://baidu.com 的服务器(nginx)进行了如下跨域配置,看到这个请求,一对比,可以啊兄弟,我允许你访问。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

那请求就可以正常进行下去,否则会触发XHR的error。


上面介绍的,是简单请求的过程,如下图所示。(请求类型分为简单请求和复杂请求,建议访问https://www.test-cors.org/进行实际的测试来观测)
在这里插入图片描述
对于复杂请求来说,多了一步使用OPTIONS的预检操作,流程差不多。
在这里插入图片描述

2.3 tomcat 解决跨域

对于tomcat来说,配置一个filter就可以了。

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

2.4 SpringBoot 服务解决跨域

方式1:Controller类或方法上添加@CrossOrigin注解

方法上标注@CrossOrigin只针对当前方法支持跨域

@RestController
@RequestMapping("/account")
public class AccountController {
 
    @CrossOrigin
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
 
    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

类上标注@CrossOrigin 当前类中所有方法都支持跨域

@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
 
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
 
    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

方式2:全局CORS配置

除了上述细粒度、基于注解的配置之外,你还可能需要定义一些全局CORS配置。这类似于使用筛选器,可以结合@CrossOrigin配置。

全局方式1: 采用过滤器(filter)

/**
 * 跨域请求配置
 */
@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许的请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许的请求源 (如:http://localhost:8080)
        corsConfiguration.addAllowedOrigin("*");
        // 允许的请求方法 ==> GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
        corsConfiguration.addAllowedMethod("*");
        // URL 映射 (如: /admin/**)
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(urlBasedCorsConfigurationSource);
    }
}

全局方式2: 继承WebMvcConfigurerAdapter或者实现WebMvcConfigurer接口

/**
 * AJAX请求跨域
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    static final String ORIGINS[] = new String[]{"GET", "POST", "PUT", "DELETE"};

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods(ORIGINS)
                .maxAge(3600);
    }
}

注意:

  1. 微服务环境下,建议在gateway中添加配置类,解决整个系统的跨域问题。
  2. 如果在gateway中处理了跨域问题,不要再在各个微服务中处理跨域,否则会导致跨域请求失败。

3 总结

跨域问题,在前后分离的架构下,几乎100%都会遇到。跨域访问的限制,是浏览器做的文章,我们可以使用CORS来绕过去。既然是绕,那就不要一股脑的全部设置成 * ,虽然这样搞非常的让人省心。

有时候你确实会遇到连CORS都处理不了的跨域问题。在这种情况下,最好要求你的客户,升级一下支持的浏览器试试。毕竟有些特立独行的浏览器,是非常IE的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

请求跨域 CORS policy: No ‘Access-Control-Allow-Origin‘ 的相关文章

  • 监控显卡显存(python代码)

    一 前言 我和我同学的代码 分别占用14G显存 而显卡的显存只有24G 没有办法同时跑 所以 他先跑 我的代码时刻监控显存的使用情况 只要显卡显存大于14G 我的代码就自动启动 二 代码 import pynvml import time
  • uni.ownloadFile下载下来的文件没有后缀名

    let filepathss plus io convertLocalFileSystemURL data tempFilePath plus io resolveLocalFileSystemURL filepathss function
  • Vue + Element-ui组件上传图片报错问题解决方案

    在使用Vue和Element ui组件上传图片时 可能会遇到一些报错问题 以下是一些常见的问题及解决方案 报错 TypeError Cannot read property name of undefined 解决方案 这个错误通常是因为在
  • 【网络安全】web漏洞-xml外部实体注入(XXE)

    web漏洞 xml外部实体注入 XXE 目录 web漏洞 xml外部实体注入 XXE 概念 危害 检测方法 利用方法 漏洞利用 xxe lab 有回显情况 无回显情况 pikachu靶场
  • 拼多多详情API开启运营比价新纪元

    随着互联网的快速发展 电商行业正在迅速崛起 拼多多作为一家新兴的电商平台 凭借其独特的营销策略和创新的商业模式 成为了电商行业的一匹黑马 在拼多多的成功背后 其详情API接口营销起到了至关重要的作用 本文将详细介绍拼多多详情API接口营销的
  • ECMAScript简介及特性介绍

    ECMAScript 简称ES 是JavaScript的规范 同时也是被广泛采用和实现的脚本语言标准 从最初的1996年推出第一版至今 ECMAScript已经经历了数十年的发展和改进 成为了互联网开发中的重要基石之一 本文将对ECMASc
  • 如何给 unplugin-vue-components/vite 写一个简单的 resolver

    大部分工作 unplugin vue components 都已经处理好了 我们只需要接收组件名来判断是否是自己的组件 然后处理对应的导入逻辑 一共 3 个字段 as 重命名类似 import componentNameReName fro
  • ❤ Vue3 使用

    Vue3 使用 Vue3之toRefs的使用 作用 toRefs 可以将一个响应式的对象 转换成普通对象 但是转换后的普通对象的每一个属性值都是响应式的 这样我们可以使用es6的对象解构或者三点运算符等操作 代码
  • 38条Web测试经验分享

    1 页面链接检查 每一个链接是否都有对应的页面 并且页面之间切换正确 可以使用一些工具 如LinkBotPro File AIDCS HTML Link Validater Xenu等工具 LinkBotPro不支持中文 中文字符显示为乱码
  • 前端必备的 web 安全知识手记

    前言 安全这种东西就是不发生则已 一发生则惊人 作为前端 平时对这方面的知识没啥研究 最近了解了下 特此沉淀 文章内容包括以下几个典型的 web 安全知识点 XSS CSRF 点击劫持 SQL 注入和上传问题等 下文以小王代指攻击者 话不多
  • 每天10个前端小知识 <Day 6>

    前端面试基础知识题 1 使用js实现二分查找 二分查找 也称为折半查找 是指在有序的数组里找出指定的值 返回该值在数组中的索引 查找步骤如下 从有序数组的最中间元素开始查找 如果该元素正好是指定查找的值 则查找过程结束 否则进行下一步 如果
  • 每天10个前端小知识 <Day 5>

    前端面试基础知识题 1 typeof 与 instanceof 有什么区别 typeof与instanceof都是判断数据类型的方法 区别如下 typeof会返回一个变量的基本类型 instanceof返回的是一个布尔值 instanceo
  • Android SDK开发艺术探索(五)安全与校验

    一 前言 本篇是Android SDK开发艺术探索系列的第五篇文章 介绍了一些SDK开发中安全方面的知识 包括资源完整性 存储安全 权限校验 传输安全 代码混淆等知识 通过基础的安全配置为SDK保驾护航 探索SDK开发在安全方面的最佳实践
  • 基于java的饮食分享平台系统设计与实现

    基于java的饮食分享平台系统设计与实现 I 引言 A 研究背景和动机 近年来 随着人们生活水平的提高和健康意识的增强 饮食健康已经成为越来越多人的关注焦点 因此 一个方便快捷的饮食分享平台就显得尤为重要 基于Java的饮食分享平台系统设计
  • Vue3 和Vue2的区别,以及钩子函数的使用

    Vue js 3 和 Vue js 2 是两个主要版本的流行前端框架 它们之间有很多区别 包括性能优化 新特性和改进的API等 以下是一些Vue 3与Vue 2之间的主要区别 以及一些示例代码来说明这些差异 1 性能优化 响应式系统 Vue
  • 低代码配置-属性配置面板设计

    模块设计 tab项切换 组件基础属性 组件数据属性 组件事件属性 表单属性 模块输出函数设计 tab切换函数 列表表单属性 数据来源 调用接口时一次赋予 无需使用selectItem 如需使用 归入基础属性 列表标题 是否展示筛选区域
  • 30天精通Nodejs--第十九天:express-文件上传下载

    目录 前言 环境准备与依赖安装 文件上传功能实现 引入并配置express fileupload中间件 注意事项 文件下载功能实现 结语 前言 文件的上传和下载是许多应用程序必备的功能 Node js的Express框架同样可以通过集
  • chrome浏览器无法在地址栏输入内容搜索问题解决--图文

    关于日常遇到的小问题解决记录一下 1 导航栏录入信息后跳转错误 2 解决办法 默认百度搜索引擎地址错误 百度正确的搜索格式是 http www baidu com s wd s chrome浏览器中百度的搜索格式是 http www bai
  • 考虑光伏出力利用率的电动汽车充电站能量调度策略研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码 数据
  • Vue中下载不同文件常用的方式

    1 使用window open方法下载文件

随机推荐

  • 基于LSTM的交通工具轨迹预测

    网络上利用LSTM预测轨迹的文章不多 仅有的几篇比较粗略 本文对一些大佬开源的代码进行修改 增添了轨迹连续预测代码 不足之处欢迎批评 本文参考Muzi Water大佬的文章 LSTM模型 轨迹经纬度预测 https blog csdn ne
  • 2022 年十大 Python Web 开发框架

    1 Django Django 框架是任何 Web 开发公司的首选 开发人员使用此框架来开发高质量标准的复杂 Web 和移动应用程序 由于其开源特性 Django 具有成本效益 但在其他有助于开发人员创建 API 和业务类 Web 应用程序
  • 大题---砝码称重(贪心算法)

    5个砝码 用天平称重时 我们希望用尽可能少的砝码组合称出尽可能多的重量 如果只有5个砝码 重量分别是1 3 9 27 81 则它们可以组合称出1到121之间任意整数重量 砝码允许放在左右两个盘中 本题目要求编程实现 对用户给定的重量 给出砝
  • Redis多机数据库实现

    Redis多机数据库实现 为 Redis设计与实现 笔记 复制 客户端可以使用SLAVEOF命令将指定服务器设置为该服务器的主服务器 127 0 0 1 12345 gt SLAVEOF 127 0 0 1 6379 127 0 0 1 6
  • Date类(Date、SimpleDateFormat和Calendar)使用

    1 Date类与long数据类型的转型 2 SimpleDateFormat类的使用 3 Calendar类的使用 如果要操作日期一定要使用日期的处理类 1 Java util Date类 范例 package com lohas demo
  • Win10/Win11子系统(二)——深度学习环境搭建:WSL2+Ubuntu20.04+CUDA10.1+pytorch1.8.1+pycharm

    windows子系统wsl2深度学习环境配置 前言 一 准备工作 显卡驱动 二 CUDA10 1配置 1 下载安装 2 设置环境变量 三 cudnn配置 3 检验安装 四 安装Anaconda 五 安装pytorch 六 安装pycharm
  • hexo实现背景花瓣飞舞效果

    效果 步骤 在source目录下js文件中新增petal js文件 var RENDERER INIT CHERRY BLOSSOM COUNT 30 MAX ADDING INTERVAL 10 init function this se
  • 在PLC中USINT和BYTE的区别

    这两种数据类型的大小和使用范围一样 大小是8位 范围是0到255 但是BYTE可以直接对数据的某一位操作 比如BYTE类型 byData X5 TRUE 表示把byData二进制数据的第五位直接置为1 与BYTE功能类似的16和32位数据类
  • 什么是“懒加载”(Lazy Loading)?

    懒加载 也被叫作 延迟价值 它的核心思想是把对象的实例化延迟到真正调用该对象的时候 这样做的好处是可以减轻大量对象在实例化时对资源的小号 而不是在程序初始化的时候就预先将对象实例化 另外 懒加载 可以将对象的实例化代码从初始化方法中独立出来
  • EasyGBS针对数据库删除级联数据后的无效数据进行的优化

    EasyGBS国标视频云服务可支持通过国标GB28181协议将设备接入 实现视频的实时监控直播 录像 语音对讲 云存储 告警 级联等功能 同时也支持将接入的视频流进行全终端 全平台分发 分发的视频流包括RTSP RTMP FLV HLS W
  • linux学习,配置bond

    什么是bond bond是一种虚拟网卡的技术 可以把几块网卡联系起来 虚拟成一块网卡来对外提供服务 通俗一点就是服务器两个网口怼两根线 把这两个真实存在的网口绑定成一个虚拟的网卡 叫bond0 然后把ip配到bond0 它的网速就从1000
  • 有什么资格抱怨?

    那些轻描淡写抱怨没有机会说自己苦逼的人 请你们扪心自问 当 小四川 捧着一本 操作系统 睡着的时候 你们在干吗 当 老灵通 这个五音不全的人 为了英语发音稍微好听点 把一段话背诵上百遍时 你们在干吗 当我捧着字典 啃着几斤重的英文版 管理会
  • VSCode最新版安装教程(非常详细),从零基础入门到精通,看这篇就够了

    VSCode 简介 Visual Studio Code 简称 VS Code VSC 是微软公司推出的一款免费开源的现代化轻量级代码编辑器 支持几乎所有主流的开发语言的语法高亮 智能代码补全 GIT 等特性 支持插件扩展等等 推荐理由 比
  • linux web项目部署到tomcat服务器

    192 168 1 11 192 168 1 12 192 168 1 13 tomcat tomcat123 ll 查看当前目录 cd 进入目录 ps ef grep tomcat query 查看进程 查看进程号 kill 9 进程号
  • 锂电池充电——NTC温度控制电路

    目录 JEITA标准 the Japan Electronics and Information Technology Industries Association NTC 负温度系数热敏电阻 型号 103AT 2 阻值 温度采样电路 TS
  • 联表查询和嵌套查询—读懂数据库仓储

    数据仓储不像java C JS等开发语言 而是数据库仓储更多用于对接产品工作 查询数据 分析数据 得出产品未来发展方向 与产品经理相关联 而联表查询和嵌套查询作为数据库基础的查询方法 学习使用 方便技术人员从数据库的角度收集数据 给产品经理
  • 配置Sub-VLAN跨交换机的Super-VLAN

    示例图 一 实验目的 1 Sub VLAN跨交换机的Super VLAN 二 注意事项 1 必须先创建配置每个sub vlan 再创建 配置Super vlan 2 当Super vlan开启了 VLAN内ARP代理功能时 各个sub vl
  • java定义一个全局map_Java中关于Map的九大问题

    通常来说 Map是一个由键值对组成的数据结构 且在集合中每个键是唯一的 下面就以K和V来代表键和值 来说明一下java中关于Map的九大问题 1 将Map转换为List类型 在java中Map接口提供了三种集合获取方式 Key set va
  • VS2015同时将调试信息输出到终端和文件

    下载wtee https github com gvalkov wtee 将wtee exe放到 C Windows System32 目录下 在VS工程的 属性页 gt 配置属性 gt 调试 gt 命令参数一栏的最后面添加 wtee my
  • 请求跨域 CORS policy: No ‘Access-Control-Allow-Origin‘

    目录 1 跨域和同源 2 CORS 跨域资源共享 解决跨域 2 1 前端解决 不推荐 2 2 Nginx 解决跨域 2 3 tomcat 解决跨域 2 4 SpringBoot 服务解决跨域 3 总结 如在浏览器控制台看到类似于下边的报错