CORS 跨域问题解决预检(OPTIONS)请求解释

场景:

业务要求从把系统B嵌入到系统A中,系统A和系统B是完成不同的两个域名,前端同事完成系统嵌入后,从A系统内部调用B系统的接口时候发现跨域错误(CORS error),如下:
在这里插入图片描述

什么是跨域?

跨域(Cross Origin)指浏览器不允许当前页面所在的源去请求另一个源的数据,跨域也就是跨源的意思。

什么是同源?

同源策略(SOP Same origin policy):是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也是最基本的安全功能,如果缺少同源策略,浏览器很容易受到XSS、CSFR等攻击,所谓同源是指"协议+域名+端口"三者相同,必须满足这三个条件,才算做同源。

跨域具体场景举例:

当前页面 url 地址被请求页面 url 地址是否跨域原因
https://www.poratl.comhttps://www.poratl.com/index协议+域名+端口 三者相同
https://www.poratl.comhttp://www.poratl.com协议不同,http、https
https://www.poratl.comhttps://www.portal.com主域名不同
https://www.poratl.comhttps://hy.portal.com子域名不同
https://www.poratl.com:10000https://www.poratl.com:10010端口不同

什么原因导致浏览器报跨域错误?

发起ajax请求的那个页面的地址 和 ajax接口地址 不在同一个域中,直接导致了跨域问题,也就是说跨域问题发生在浏览器。

跨域问题解决方案:

Nginx 反向代理解决跨域

Nginx 反向代理解决跨域,只需要在 nginx 上增加配置文件,即可解决跨域问题,如下:

server {listen       80;listen       443;server_name  xxx.test.com;root /usr/share/nginx/html;index  index.html index.htm;#跨域配置	add_header Access-Control-Allow-Methods GET,POST,PUT,OPTIONS,DELETE,PATCH;add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers *; #access_log   /data/logs/nginx/nginx_elk_log/test.com.access.log nginx-json-log;#error_log   /data/logs/nginx/nginx_elk_log/test.com.error.log;if ($request_method !~* GET|POST|HEAD) {return 403;}location / {#跨域配置(和上面的跨域配置二选一即可)add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers *;add_header_Access-Control-Allow-MethodS GET,PUT,DELETE,POST,OPTIONS;#另外一种配置方式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,PUT,DELETE,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';return 204;}#root   /data/web/html/zteam;root   /usr/share/nginx/html;index  index.html index.htm;try_files $uri $uri/ /index.html;}location ^~ /WEB-INF{deny all;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}

Nginx 增加配置解决跨域问题,只使用一种解决问题即可,不要同时配置多个。

Nginx 知识传送门:
Nginx 故障排查之斜杠(/) --(附 Nginx 常用命令)

服务端解决跨域问题

解决 CORS 跨域问题,就是在服务器端给响应添加头信息,解释如下:

Access-Control-Allow-Origin 允许请求的域
Access-Control-Allow-Methods 允许请求的方法
Access-Control-Allow-Headers 预检请求后,告知发送请求需要有的头部
Access-Control-Allow-Credentials 表示是否允许发送cookie,默认false;
Access-Control-Max-Age 本次预检的有效期,单位:秒;

1、使用过滤器解决跨域问题,注意该方案需要在启动类加注解:@ServletComponentScan({“com.my.study.main.filter”}

package com.my.study.main.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @ClassName: CorsFilter* @Author: zhangyong* @Date: 2024/4/8 17:35* @Description:*/
@Slf4j
@Component
@WebFilter(urlPatterns = { "/*" })
public class MyCorsFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;log.info("进入了过滤器,请求路径为:{}",request.getRequestURL());HttpServletResponse httpServletResponse = (HttpServletResponse)servletResponse;// 允许跨域的域名,*:代表所有域名httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");// 允许跨域请求的方法httpServletResponse.setHeader("Access-Control-Allow-Methods",  "POST, PUT, GET, OPTIONS, DELETE");// 本次许可的有效时间,单位秒,过期之前的ajax请求就无需再次进行预检啦// 默认是1800s,此处设置1hhttpServletResponse.setHeader("Access-Control-Max-Age", "3600");// 允许的响应头httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");// 支持HTTP 1.1.httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");// 支持HTTP 1.0. response.setHeader("Expires", "0");httpServletResponse.setHeader("Pragma", "no-cache");// 编码httpServletResponse.setCharacterEncoding("UTF-8");// 放行filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}}

2、过滤器解决跨域的另外一种实现方式。

package com.my.study.main.configurer;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;/*** @ClassName: CorsConfig* @Author: zhangyong* @Date: 2024/4/8 13:41* @Description:*/
@Configuration
public class CorsConfig {private CorsConfiguration buildConfig() {CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*");corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");corsConfiguration.setMaxAge(3600L);         corsConfiguration.setAllowCredentials(true);return corsConfiguration;}@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", buildConfig());return new CorsFilter(source);}
}

2、添加 @Configuration 注解,实现 WebMvcConfigurer 接口,解决跨域问题。

package com.my.study.main.configurer;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration 
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 所有接口.allowCredentials(true) // 是否发送 Cookie.allowedOriginPatterns("*") // 支持域.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法.allowedHeaders("*").exposedHeaders("*");}

跨域解决方案总结:
推荐使用 Nginx 处理跨域问题,只需要在nginx 上增加配置即可解决问题,而服务端解决跨域问题,或多或少都需要写代码,本着少改代码的原则,强烈建议使用 Nginx 的方式解决跨域问题,不管使用哪种方式解决跨域问题,只需要使用一种即可,不要多种方式叠加使用。

温馨提示:
跨域问题通常是伴随多个系统一起出现了,也就是出现了跨系统调用,可能会出现跨域问题,这个时候要主要多个系统的权限认证是否通用,如果权限认证不通用,要优先解决权限认证的问题,否则也是提示跨域问题,浏览器端常见错误如下:
在这里插入图片描述

什么是预检(OPTIONS)请求?

浏览器使用 OPTIONS 方法发起一个预检请求(preflight request),来感知服务端是否允许该跨域请求,服务器确认允许之后,才发起实际的 HTTP 请求,OPTIONS 请求没有附带请求数据,响应体也为空,简单来说就是一种探测,这就是预检请求,是浏览器的一种保护机制。

预检(OPTIONS)请求的作用?

  • 跨域场景中使用了预检请求,跨域请求失败产生错误,代码层无法获知感知错误发生的地方,这时候可以查看浏览器的控制台来查询错误信息。
  • 检测服务器支持的请求方法。

什么时候会触发预检(OPTIONS)请求?

非简单请求时候会触发预检请求。

简单请求与非简单请求:

简单请求:

  • 请求方法是 GET、HEAD、POST 中的一种。
  • HTTP的头信息只能是 Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type 中的某几个,不能超出这个范围。
  • Content-Type 的值只能是 text\plain、multipart/form-data、application/x-www-form-urlencoded 中的一种。
  • 请求中没有使用 XMLHttpRequestUpload 对象。
  • 请求中没有使用 ReadableStream 对象。

非简单请求:
简单请求的对立面就是非简单请求,也就是说不能同时满足简单请求条件的请求就是非简单请求,就可能会触发预检(OPTIONS)请求。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817022.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode开发 vue3+ts 的 uni-app 微信小程序项目

创建uni-app项目: # 创建用ts开发的uni-app npx degit dcloudio/uni-preset-vue#vite-ts 项目名称 # 创建用js开发的uni-app npx degit dcloudio/uni-preset-vue#vite 项目名称VS Code 配置 为什么选择 VS Code ? HbuilderX 对 TS 类型支持暂不完善VS…

(学习日记)2024.04.16:UCOSIII第四十四节:内存管理

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…

手机数据恢复工具

下载地址:手机数据恢复工具.zip Android/HarmonyOS 文件误删是日常使用电子设备时经常遇到的问题,也许一不小心就就可能会误删。 俗话说:数据无价,一但想要找回一些被删除的文件,就需要耗费大量的精力和财力来恢复文…

【宝德PI300T G2智能小站开发教程(三)】centos配置系统开发源

目录 一.前言 二.配置dns服务器 三.测试连通性 四.设置更新源文件 一.前言 openeular系统的宝德板子没有更新的国内源,要如何配置? 二.配置dns服务器 vi /etc/resolv.conf 添加如下内容: nameserver 8.8.8.8 nameserver 114.114.114.114 三.测试连通性 ping www.ba…

vscode远程连接centos

文章目录 vacode连接linux1. 安装插件2. 查看配置3. 打开ssh4. 远程连接 vacode连接linux 1. 安装插件 在扩展栏搜索remote ,找到Remote Development插件,进行安装: 2. 查看配置 打开自己的linux终端,输入ifconfig,…

Laravel/Lumen 中使用 Echo + Socket.IO-Client 实现网页即时通讯广播

此处以 Lumen 9 框架为例说明如何调试通过 Echo 服务端以及客户端 如果你是 Laravel/Lumen 10.47 用户,可以先了解官方的 Laravel Reverb。注意 Laravel Reverb 仅支持 Laravel/Lumen 10.47 以及 PHP 8.2Laravel Reverb 参考官网:https://laravel.com/d…

CSS导读 (复合选择器 下)

(大家好,今天我们将继续来学习CSS的相关知识,大家可以在评论区进行互动答疑哦~加油!💕) 目录 2.5 伪类选择器 2.6 链接伪类选择器 2.6.1 链接伪类注意事项 2.6.2 链接伪类选择器实际开发中的写法 2.7 …

智慧医疗app

智慧医疗app是一套融合物联网、云计算和大数据等技术,以患者数据为中心的医疗服务模式,致力于为患者提供更加便捷、高效的医疗服务。 在线挂号、在线问诊、电子病历记录、健康管理以及药品购买等。患者可以通过app选择医生和挂号时间,并在线…

ROS2从入门到精通1-3:详解ROS2动作通信机制与自定义动作

目录 0 专栏介绍1 动作通信模型2 动作模型实现(C)3 动作模型实现(Python)4 自定义动作 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情&a…

蓝桥杯嵌入式2021年第十二届第一场省赛主观题解析

1 题目 2 代码 /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h"/* Private includes…

武汉星起航助力跨境电商,专业选品与全方位服务引领行业新风尚

在全球跨境电商浪潮的推动下,越来越多的卖家纷纷将目光投向了这片广阔的市场。然而,如何在这片蓝海中脱颖而出,成为众多卖家关注的焦点。武汉星起航电子商务有限公司以其专业的选品建议和全方位的服务,为卖家们提供了一条成功的捷…

新零售行业门店管理方案详解,人人都可以是好店长

在之前的文章中,我们分别介绍了新零售业的全面解决方案,包括门店管理解决方案、商品经营方案、会员管理解决方案,以及这些方案所包含的分析指标,吸引了不少对新零售转型感兴趣的企业主。 后续我们会将这些内容拆解开来&#xff0…

LeetCode-热题100:104. 二叉树的最大深度

题目描述 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入: root [3,9,20,null,null,15,7] 输出: 3 示例 2: 输入: root …

【数字IC/FPGA】什么是无符号数?什么是有符号数?

进制 虽然在日常生活中,我们已经习惯了使用10进制数字,但在由数字电路构成的数字世界中,2进制才是效率更高的选择。 10进制与2进制 10进制(decimal)计数法(一般也叫阿拉伯计数法)是在日常生活…

LLM生成模型在生物单细胞single cell的应用:scGPT

参考: https://github.com/bowang-lab/scGPT https://www.youtube.com/watch?vXhwYlgEeQAs 主要是把单细胞测序出来的基因表达量的拼接起来构建成的序列,这里不是用的基因的ATCG,是直接用的基因名称 训练数据:scGPT全人模型是在3…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后,会触发一个Reblanceing数据重分布的机制,简单的理解就是将扩缩容前后OSD…

【Hello算法】 > 第 1 关 > 初识 算法 与 复杂度分析

初识 算法 与 复杂度分析 What are algorithms and data structures ?-什么是算法与数据结构?How to conduct complexity analysis ?-如何进行复杂性分析?时间复杂度空间复杂度 小结Tips: ————————————————————————…

Day101:漏洞发现-漏扫项目篇NucleiYakitGobyAfrogXrayAwvs联动中转被动

目录 特征类-三方Poc调用&模版Poc调用 案例1:单点对某特征点进行安全评估 Goby-综合类 Nuclei-较综合类 Afrog-特征类 Yakit-可特征可综合 案例2:新型对某特征点进行安全评估 综合类-主动漏扫&中转联动&被动联动 案例1:…

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑,这些问题可能会影响我们的开发效率和代码质量,因此我们需要不断总结和学习,以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结,以提高大家的开发质量。本系列文章…

03-进程-网络命令-软件安装-SSH免密登录

软件安装-网络命令-SSH免密登录 一 软件安装 1 在线安装 命令: yum 作用:yum会从指定的服务器自动下载rpm包并且进行安装,优点是可以自动处理依赖关系,并且一次安装所有的软件包。 配置yum的镜像源 yum源有个统一的下载服务…