24.什么是跨域?解决方案有哪些?

news2024/11/18 13:28:07

为什么会出现跨域问题

存在浏览器同源策略,所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到,跨域限制主要的目的就是为了用户的上网安全。

同源策略导致的跨域是浏览器单方面拒绝响应数据,服务器端是处理完毕并做出了响应的。

什么是同源策略

一个url由三部分组成:协议,域名(ip地址),端口

只有当协议,域名,端口都一致的时候,才被称为同源。

而同源策略规定,只有发送请求的那一边和接受请求的那一边处于同源的情况下,浏览器才会接受响应。

常见的跨域场景:

而当我们的请求不符合同源策略的时候。往往会出现以下错误👇

什么是跨域及怎么解决跨域问题?[通俗易懂]

跨域的常见解决方案

jsonp

jq的ajax自带解决跨域的方法。底层原理采用的JSONP的跨域解决方案。如下

function callback(){
    console.log("这是打印日志")
}

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp  设置跨域的重点
    jsonpCallback: "callBack",  // 回调函数
});

jsonp跨解实现流程:

添加响应头解决

CORS简介

CORS是一个W3C标准,全称是"跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源(协议 + 域名 + 端口)服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。它的通信过程,都是浏览器自动完成,不需要用户参与。

对于开发者来说,CORS通信与同源的AJAX/Fetch通信没有差别,代码完全一样。浏览器一旦发现请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。

浏览器发出CORS非简单请求,会在正式通信之前,增加一次OPTIONS查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

简单请求就是HEAD、GET、POST请求,并且HTTP的头信息不超出以下几种字段 Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type 注:Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

反之,就是非简单请求。

其实实现CORS很简单,就是在服务端加一些响应头,并且这样做对前端来说是无感知的,很方便。

详解响应头:

  • Access-Control-Allow-Origin 该字段必填。它的值要么是请求时Origin字段的具体值,要么是一个*,表示接受任意域名的请求。
  • Access-Control-Allow-Methods 该字段必填。它的值是逗号分隔的一个具体的字符串或者*,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
  • Access-Control-Expose-Headers 该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
  • Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie.默认情况下,不发生Cookie,即:false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true。如果服务器不要浏览器发送Cookie,删除该字段即可。
  • Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有效期,单位为秒。在有效期间,不用发出另一条预检请求。

顺便提一下,如果在开发中,发现每次发起请求都是两条,一次OPTIONS,一次正常请求,注意是每次,那么就需要配置Access-Control-Max-Age,避免每次都发出预检请求。

Access-Control-Allow-Origin响应头的意思是,安全同行的请求。

举个例子 http://192.168.0.103:8080 向http://192.168.0.102:8080 发送了请求,结果因为域名不一样,在返回信息的时候因为IP地址不一致被拦截。

但是如果http://192.168.0.102:8080 在响应头中的 Access-Control-Allow-Origin 字段中携带上属性值'http://192.168.0.103:8080' 如下

//响应头
Access-Control-Allow-Origin':'http://192.168.0.103:8080'

这就等于告诉浏览器,http://192.168.0.102:8080 这个地址是安全的,请不要拦截。

这样,http://192.168.0.103:8080 就可以接受来自 http://192.168.0.102:8080 返回的信息。

当然,我们也可以进行所有域名均不拦截的设置(如下)

//响应头
// * 代表所有域名均不拦截
Access-Control-Allow-Origin':'*'
过滤器解决跨域
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}
使用@CrossOrigin注解
public class GoodsController {
@CrossOrigin(origins = "http://localhost:4000")
@GetMapping("goods-url")
public Response queryGoodsWithGoodsUrl(@RequestParam String goodsUrl) throws Exception {}
}  

Nginx代理跨域

location / {  
    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;
    }
    proxy_pass http://192.168.12.12:8081;
} 

给OPTIONS 添加 204的返回原因:是为了处理在发送POST请求时Nginx依然拒绝访问的错误,发送"预检请求"时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。

预检请求(preflight request)

跨域资源共享(CORS)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。  

其实Content-Type字段的类型为application/json的请求就是上面所说的搭配某些 MIME 类型的 POST 请求,CORS规定,Content-Type不属于以下MIME类型的,都属于预检请求。

网关解决跨域

@Configuration
public class GlobalCorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
        config.addAllowedOrigin("*");
        // 放行的请求头
        config.addAllowedHeader("*");
        // 放行的请求方式,主要有:GET, POST, PUT, DELETE, OPTIONS
        config.addAllowedMethod("*"); 
        // 暴露头部信息
        config.addExposedHeader("*"); 
        // 是否发送cookie
        config.setAllowCredentials(true); 

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

总结

跨域全称为Cross-Origin Resource Sharing,意为跨域资源共享,是一种允许当前域(domain)的资源被其他域(domain)的脚本请求访问的机制,通常由于同源安全策略,浏览器会禁止这种跨域请求。

本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

OPC UA与IEC61499 在分布式智能电网中的应用

储能系统的系统架构 CMC :Cell Management Controller 储能设备中的电池芯包与电池均衡系统构成电池模组,国内的电池芯包通常使用被动均衡技术,被动均衡芯片通常通过SPI 接口连接到CMC 控制器,CMC 以单片机为主构建,具…

C语言——单链表实现数据增删查改

一.前言 嗨嗨嗨,我们又见面了。前面我们已经学习了关于数据结构中的顺序表,今天我们来学习数据结构中的单链表。废话不多说让我们直接开始吧。 二.正文 1.1链表的概念 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺…

“云卷数潮”云原生数据库分论坛亮点回顾!

4月29日,2024中国移动算力网络大会“云卷数潮”云原生数据库分论坛在江苏苏州举行。本次论坛不仅是技术交流的盛宴,更是行业发展趋势的风向标。论坛汇聚了众多企业领袖、专家学者及行业精英,共话云原生数据库技术发展,探讨行业最新…

无人机+大载重+长航时:油电混动多旋翼无人机技术详解

多旋翼无人机是一种具有三个及以上旋翼轴的特殊的无人驾驶旋翼飞行器。具有稳定性强、操控简单、勤务性高、价格便宜等优势,因此在市场上的应用非常广泛。此外,利用地面供电的绳系多旋翼通过电缆向多旋翼持续传输电能,可以大大提高多旋翼的空…

QT程序通过GPIB-USB-HS转接线控制数字万用表

1、硬件准备 1.1、数字万用表 型号 :Agilent 34401A 前面图示: 后面图示:有GPIB接口 1.2、GPIB-USB-HS转接线 2、GPIB协议基础了解 2.1、引脚 8条数据线:DIO1 ~ DIO8 5条管理线:IFC、ATN、REN、EOI、SRQ 3条交握线…

2024年五一杯高校数学建模竞赛(C题) 建模解析| 冲击地压危险预测 |小鹿学长带队指引全代码文章与思路

我是鹿鹿学长,就读于上海交通大学,截至目前已经帮200人完成了建模与思路的构建的处理了~ 本篇文章是鹿鹿学长经过深度思考,独辟蹊径,通过滑动平均法解决冲击地压危险预测问题。实现综合建模。独创复杂系统视角&#xf…

Android滑动冲突解决方案面试问题及回答

问题 1: 什么是滑动冲突?在Android开发中常见哪些类型? 答案: 滑动冲突通常发生在多个滑动组件(如ScrollView, ListView, ViewPager等)嵌套使用时,各个组件对同一个滑动事件的响应发生冲突。常见的类型包括垂直滑动冲…

Flask教程1:flask框架基础入门,路由、模板、装饰器

文章目录 一、 简介二、 概要 一、 简介 Flask是一个非常小的Python Web框架,被称为微型框架;只提供了一个稳健的核心,其他功能全部是通过扩展实现的;意思就是我们可以根据项目的需要量身定制,也意味着我们需要学习各…

算法:双指针题目练习

目录 题目一:移动零 题目二:复写零 题目三:快乐数 题目四:盛最多水的容器 题目五:有效三角形的个数 题目六:和为s的两个数字(剑指offer) 题目七:三数之和 题目八:四数之和 常…

翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一

合集 ChatGPT 通过图形化的方式来理解 Transformer 架构 翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深…

CAD的DWG文件如何进行搜索文字

1.目的 想搜索CAD文件中的数字或文字是否存在DWG文件中。 2.方法 方式1:菜单栏 编辑→查找 方式2:指令格式 图纸的左下侧→命令处,进行输入find→再按回车enter 3.结果

Day 22 SSH远程管理服务

sshd服务,系统自带,默认开机自启运行 云/物理服务器的安全组和防火墙默认放行该端口 软件包:openssh-server(服务端);openssh-client(客户端); 格式:ssh I…

【C++语法练习】计算梯形的面积

题目链接:https://www.starrycoding.com/problem/158 题目描述 已知一个梯形的上底 a a a,下底 b b b和高 h h h,请求出它的面积(结果保留两位小数)。 输入格式 第一行一个整数 T T T表示测试用例个数。 ( 1 ≤ T …

JeeSite主子表

classroom表代码生成配置(主表) student表代码生成配置(子表) 设置“班级”菜单 班级列表页面 点击“三年级二班”,显示班级中的学生列表页面 班级表 CREATE TABLE classroom (classroom_id int NOT NULL AUTO_…

Meditron:基于 Llama 完全开源的医学大语言模型

健康危机就在眼前,当医疗资源有限时,每一秒钟都至关重要!Meditron 就像一位忠实的医疗助手,提供基于证据的护理建议和情境意识的推荐,帮助医疗工作者在诊断和治疗过程中做出更准确的决策。 在资源有限的医疗环境中&am…

C/C++实现高性能并行计算——1.pthreads并行编程(中)

系列文章目录 pthreads并行编程(上)pthreads并行编程(中)pthreads并行编程(下)使用OpenMP进行共享内存编程 文章目录 系列文章目录前言一、临界区1.1 pi值估计的例子1.2 找到问题竞争条件临界区 二、忙等待三、互斥量3.1 定义和初始化互斥锁3.2 销毁。3.3 获得临界区的访问权&…

《读懂财务报表》手绘版读书笔记:通过报表找好公司

通过财报的三张表判断好公司: 然后是在三表中,计算各个项目占总体的比例,以及做比率分析, 比率分析,从偿还能力,运营能力,盈利能力三方面分析: 1) 偿还能力 2&#xff09…

新建stm32工程模板步骤

1.先使用keil新建一个project的基本代码 2.stm32启动文件添加 将stm32的启动文件,在原工程当中新建一个Start文件夹把相关的启动文件放到文件夹当中 然后还需要找到下面三个文件 stm32f10x.h是stm32的外设寄存器的声明和定义,后面那两个文件用于配置系…

Python数据预处理1:导入与基本操作

2024/4/30 After installing the xlrd package, you should be able to read Excel files using pandas without any issues. #需要在pyCharm命令行中下载两个包 pip install pandas pip install xlrd .xls数据导入 #数据的导入 import pandas as pd #导入EXCEL表格数据 df…

Java基于微信小程序+uniapp的校园失物招领小程序(V3.0)

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…