一文带你理清同源和跨域

1、概述

前后端数据交互经常会碰到请求跨域,什么是跨域,为什么需要跨域,以及常用有哪几种跨域方式,这是本文要探讨的内容。
image-20240618160438055
同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

同源策略是一种约定,它是浏览器最核心也是最基本的安全功能。出于安全考虑,浏览器限制从JS脚本发起的跨源HTTP请求。

通俗的理解:浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:

①无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。

②无法接触非同源网页的 DOM。

③无法向非同源地址发送 Ajax 请求。

同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域。出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。

例如网页(http://www.test.com/index.html)和接口(http://www.api.com/userlist),非同源的URL,浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到。

image-20240618152346498

2、为什么要跨域?

跨域是浏览器受同源(协议、域名、端口)策略的限制,不允许不同源的站点之间进行某些操作(如发送ajax请求,操作dom,读取cookie),如果不进行特殊配置是不能操作成功的,并且控制台会报如下跨域错误:

``No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘xxxxxx’ is therefore not allowed access`

跨域的根本原因是浏览器的“同源策略”,同源 就是【协议+域名+端口号】相同,即为同源,只能向同源的服务发起AJAX请求。

image-20240618152627312

源1源2是否同源
a.comb.com🚫不同源,域名不同
http://a.comhttps://a.com🚫不同源,协议不同
a.com:80a.com:443🚫不同源,端口不同
gg.coma.gg.com🚫不同源,子域名不同
a.com/ssa.com/s2同源

可通过location.originwindow.origin获取当前文档的源

为什么要同源呢?

这是浏览器故意设计的,是浏览器的基本安全策略,否则会很容易受到XSS、CSRF攻击。只能向同源的服务发起AJAX请求,不可跨域请求,会被浏览器拦截。

有哪些限制规则呢?

  • ✅ 访问其他源的图片、CSS、JS是可以的,允许<img src="url"><link href="url"><script src="url">元素获取的其他源的资源。
  • ✅ Form表单可以跨域提交,表单的提交只是提交数据无需返回,浏览器认为是安全的。
  • 🚫 AJAX不可以向其他源发送网络请求,会被浏览器拦截。注意拦截的不是请求,而是响应,服务端依然是可以收到请求的。
  • 🚫 仅可访问自己域的cookie、localStorage、DOM树,不能访问Iframe嵌入的其他页面内部内容。

image-20240618152717403

3、如何实现跨域?

跨域请求(Cross-Origin Request),简称CORS,是指在Web开发中,当一个Web页面向不同源(域名、协议或端口)的服务器发起请求时,浏览器会遵循同源策略(Same-Origin Policy)的限制,对这些跨源请求进行限制。由于浏览器的同源策略限制,跨域请求默认是被禁止的,同源策略要求请求的协议、域名和端口必须完全一致,否则会被浏览器拦截。

随着互联网越来越复杂,需求也越来越多,跨域请求就很常见了。我们知道了跨域是浏览器的同源限制,就可以针对性的想办法了。

跨域

本文主要针对最常用的三种进行讲解,其他的可以自行参考相关文章。

3.1、JSONP跨域

这是一种传统的跨域请求办法,借助于<script>标签元素,因为<script>src可以访问任何站点的资源。当然这需要服务端对应接口支持JSONP(JSON with padding)协议,所以是需要双方约定好,所以浏览器认为这是安全的。

  • 优点是兼任IE,实现跨域。
  • 缺点是不能控制请求过程,仅支持GET方式请求。因为只是一个<script>标签,浏览器自动发起的资源请求。

JSONP(JSON with Padding)是JSON的一种”使用模式“,是一种非官方的协议,用于解决浏览器的跨域数据访问的问题。

📢前端具体实现过程:

  • 1、申明一个全局的回调函数“getData”来接收数据。
  • 2、动态创建一个<script>标签,src为要跨域的API地址,URL中带上回调参数“callback=getData”。
  • 3、服务端收到请求后,动态生成一个脚本,脚本内容是一个字符串,由回调+返回的数据构成:“getData('data')”。
  • 4、本地执行远程脚本,回调函数“getData”运行,就得到了想要的数据。
<script src="http:www.thrid.com/cors/api?q=key&callback=back"></script>
<script>function back(data) {console.log(data);}
</script>

JSONP的实现:

function jsonp(url, args, cbName) {return new Promise((resolve, reject) => {const ele = document.createElement('script');window[cbName] = (data) => {resolve(data);document.body.removeChild(ele);}args = { ...args, callback: cbName };ele.src = `${url}?${Object.keys(args).map(k => `${k}=${args[k]}`).join('&')}`;document.body.appendChild(ele);});
}
//使用,api为360的公开接口
jsonp('https://sug.so.360.cn/suggest', { format: 'jsonp', word: 'china' }, 'search').then(function (data) {console.log(data)});

3.2、CORS跨域

CORS是什么?—— 跨域资源共享 (cross-origin resource sharing),让AJAX可以跨域访问数据。这是为了满足跨域请求的需求,W3C新增加的特性,需要服务端的支持,不支持IE8/9。

当浏览器发送一个跨域请求时,它会首先发送一个预检请求(OPTIONS请求),检查后端是否支持跨域请求。这个预检请求会包含一些CORS相关的HTTP头,如Origin、Access-Control-Request-Method和Access-Control-Request-Headers。后端收到预检请求后,会检查请求中的Origin头,与自己在CORS配置中设置的allowedOrigins进行对比,如果匹配成功,就会在响应中设置相应的CORS头,如Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers等。

一旦预检请求通过,浏览器就会发送实际的跨域请求。在接收到实际请求的响应后,浏览器会再次检查响应中的CORS头,确保它们与预检请求中的设置一致。如果一切正常,浏览器就会允许前端JavaScript代码访问响应中的数据。

通过这种方式,后端通过显式配置CORS参数,告知浏览器哪些源有权访问其资源,从而实现了跨域访问的功能。这既保证了安全性(只允许指定的源进行访问),又提供了灵活性(可以根据需要配置不同的CORS策略)。

根据请求方式,浏览器将CORS分为两种情况:

  • 简单请求(安全请求):只支持GET、POST、HEAD,Header只支持部分字段。
  • 复杂请求(其他请求):简单请求以外的其他跨域请求。
🔵简单请求

基本原理就是在请求头加入一个身份来源标识,服务端根据这个标识来判等是否允许访问,如果允许则给一个允许的标记并返回响应。

  • 只支持GET、POST、HEAD。
  • header —— 我们仅能设置基础的安全字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type 的值为 application/x-www-form-urlencoded,multipart/form-data 或 text/plain。

📢具体过程比较简单,前端只要在Header加入“Origin”即可:

  • 请求头Header加入要跨域的源:origin:http://www.main.com
GET /api HTTP/1.1
Origin: http://www.main.com				//本次请求来自哪个源
Host: http://www.third.com				//请求的第三方API
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0
...
  • 服务端收到请求后检查Origin,如果同意请求则正常响应,同时在响应的Header中加入特殊的“Access-Control-Allow-Origin”字段,申明支持的源,也可以用“*”表示支持任何源访问。
  • 浏览器收到响应后会检查“Access-Control-Allow-Origin”,和当前源对比,如果不合法则会报错——跨域。
Access-Control-Allow-Origin: http://www.main.com		//请求允许的源
Access-Control-Allow-Credentials: true							//是否允许cookie,cors默认不发送cookie,如果要发送,还需AJAX中设置withCredentials
Access-Control-Expose-Headers: Content-Length,API-Key	//如果客户端想要访问其他非安全字段,则需要服务端明确定义哪些Header字段暴露出来
Content-Type: text/html; charset=utf-8

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

🟠复杂请求

不是简单请求的都称为复杂请求(非简单请求),如请求方法是PUT、DELETE,或Content-Type=application/json。相比于简单请求,复杂请求多了一次预请求。

预请求

  • 正式发送请求前,浏览器会自动发送一个预请求,问问服务端是否允许本次请求,如果回应允许才正式发送请求,后面就和简单请求相同了。
  • 预请求及其响应都没有body,采用OPTIONS方法。

image.png

JSONP 与`CORS 的对比

JSONP 是很早很成熟的解决方案,但是,只能进行 GET 请求,无法实现上传数据等操作。

反观:CORS 虽然分 预请求非预请求 ,但是,无疑支持的功能是非常强大的 !!!

3.3、Nginx反向代理

跨域是浏览器的保护机制,如果绕过浏览器,使用代理服务器去请求目标服务器上的数据,就不会受跨域影响。因此前端可以通过脚手架或webpack配置devSever下的proxy选项,将/api开头的请求转发到真实服务器上。

在生产环境下也可以使用nginx配置反向代理来解决跨域。

Nginx 则是通过反向代理的方式,(这里也需要自定义一个域名)这里就是保证我当前域,能获取到静态资源和接口,不关心是怎么获取的。

Nginx反向代理

配置下 hosts

127.0.0.1 local.test

配置 nginx

server {listen 80;server_name local.test;location /api {proxy_pass http://localhost:8080;}location / {proxy_pass http://localhost:8000;}
}

对于前端开发而言,大部分的跨域问题,都是通过代理解决的

代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域

代理适用的场景是

4、小结

因为同源是浏览器的限制,跨域的方法无非就是绕过,或采用CORS。

跨域方案基本原理是否需要服务端支持
JSONP借助<script>标签的src,加上一个全局回调函数接收数据🟠需要服务端支持JSONP协议
CORSW3C标准支持的跨域方式,请求头添加Origin字段🟠需要服务端支持
WebSocketWebSocket可以实现浏览器与服务端的双向通信,没有跨域的困惑。推荐第三方库 Socket.io,可以很方便的建立与服务端的Socket通信。🟠需要服务端支持,支持WebSocket
iframe+postMessage使用window.postMessage()来实现窗口之间的通信🔵不需服务端处理,客户端绕过
服务端代理由自己的同源服务端代理第三方的请求🟠需要服务端支持,代理请求
nginx反向代理原理和服务端代理一样,用nginx配置一个代理服务🔵不需要服务端修改代码,需nginx支持
  • CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案。
  • JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
  • 不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。
  • 日常工作中,用得比较多的跨域方案是cors和nginx反向代理。

5、参考文章

So, JSONP or CORS? - Stack Overflow

浏览器的同源策略 - Web 安全 | MDN (mozilla.org)

跨源资源共享(CORS) - HTTP | MDN (mozilla.org)

跨域资源共享 CORS 详解

Fetch:跨源请求

九种跨域方式实现原理(完整版)

前端常见跨域解决方案(全)

我把7大跨域解决方法原理画成10张图,做成图解!

值得一看的35个Redis常用问题总结http://www.guosisoft.com/article/detail/243)

国思RDIF低代码快速开发平台(支持vue2、vue3)


一路走来数个年头,感谢RDIF框架的支持者与使用者,大家可以通过下面的地址了解详情。

官方网站:http://www.guosisoft.com/ http://www.rdiframework.net/

特别说明,框架相关的技术文章请以官方网站为准,欢迎大家收藏!

RDIF.vNext低代码快速开发框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注RDIF.vNext低代码快速开发框架官方公众微信(微信号:guosisoft),及时了解最新动态。

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

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

相关文章

SN74HC14+陶瓷振子做振荡器的试验初步

面包板搭建&#xff0c;4.5V电池供电。 注意我用杜邦线插1脚并缠绕到小频谱的天线上面&#xff0c;如果直接用杜邦线转sma。请先过衰减器。 本想试验一下465khz用SN74HC14做振荡器&#xff0c;实验了很多次&#xff0c;无法起振。 用1M&#xff0c;4M的也无法起振&#xff0c;…

JavaSE 面向对象程序设计 正则表达式

正则表达式 正则表达式&#xff08;Regular Expression&#xff0c;简称Regex&#xff09;是用于匹配文本中模式的字符串表达式。它由普通字符&#xff08;例如字母、数字&#xff09;和特殊字符&#xff08;称为元字符&#xff09;组成&#xff0c;可以非常灵活地定义搜索模式…

[问题记录]Qt QGraphicsItem 移动时出现残影

目录 1.问题现象 2.问题原因 3.修改方案 1.问题现象 自定义 QGraphicsItem 时&#xff0c;绘制rect&#xff0c;对象移动时出现残影。 2.问题原因 直接原因是view未刷新的问题&#xff0c;所以网上有人使用方案 setViewportUpdateMode(QGraphicsView::FullViewportUpdate…

Linux下更新curl版本

一、前景 由于低版本的curl存在一定的漏洞&#xff0c;会对我们的服务器安全造成问题&#xff0c;所以&#xff0c;我们需要将curl由低版本安装到高版本。 二、步骤 1、首先检测服务器安装的curl版本 curl --version 2、查看服务器安装的curl的安装包 rpm -qa curl 3、卸载旧…

LabVIEW电动汽车核心部件检测系统

LabVIEW开发的电动汽车核心部件检测系统&#xff0c;通过硬件接入板和数据采集卡实现信号采集和分析。系统具备智能诊断、模块化设计和用户友好的特点&#xff0c;能够快速、精确地定位故障&#xff0c;提高电动汽车的维护效率和可靠性&#xff0c;支持新能源汽车市场的快速发展…

大数据助力电商发展||电商API接口接入

伴随互联网尤其是移动互联网的高速发展&#xff0c;电子商务已经成为人们生活中不可或缺的一部分&#xff0c;人们的购物理念和消费模式正在发生颠覆性的转变。基于天然的数据优势&#xff0c;电子商务平台利用大数据计算技术不断实施数据的累积、分析和处理&#xff0c;消费者…

windows pyenv-win:pyenv 下载过慢

先到官网下载指定版本的 exe 文件 Python Releases for Windows | Python.org 根据自己电脑的 下载 32 或者 64 下载完成后将 exe 放入 install_cache 再到 powershell 中执行安装指令 pyenv install 3.12.4

备忘录文字颜色怎么改 备忘录改变字体颜色方法

在日常的工作和生活中&#xff0c;备忘录已经成为我不可或缺的好帮手。但是&#xff0c;面对满满当当的备忘录&#xff0c;有时候不同的任务和信息都混在一起&#xff0c;让人眼花缭乱。我常常想&#xff0c;如果能改变备忘录中的文字颜色&#xff0c;用以区分不同类别的事项&a…

高清无字幕搞笑视频素材去哪里找哪里下载的?

在制作搞笑视频时&#xff0c;优质的无字幕视频素材对于提升作品的趣味性和吸引力至关重要。今天&#xff0c;我将为大家介绍一系列高清视频素材网站&#xff0c;这些网站不仅资源丰富、质量上乘&#xff0c;还能助你一臂之力&#xff0c;迅速提升视频的创意和品质。首先要推荐…

龙迅LT9611UXC 2 PORT MIPIDSI/CSI转HDMI 2.1,支持音频IIS/SPDIF输入,支持标准4K60HZ输出

龙迅LT9611UXC描述&#xff1a; LT9611UXC是一个高性能的MIPI DSI/CSI到HDMI2.0转换器。MIPI DSI/CSI输入具有可配置的单端口或双端口&#xff0c;1高速时钟通道和1~4高速数据通道&#xff0c;最大2Gbps/通道&#xff0c;可支持高达16Gbps的总带宽。LT9611UXC支持突发模式DSI视…

第二证券股市资讯:股票中什么叫龙头?

龙头&#xff0c;也就是龙头股&#xff0c;指的是某一职业中有必定影响力和号召力的股票&#xff0c;龙头股的涨跌通常对其他同职业板块股票的涨跌有必定演示和引导作用&#xff0c;是一种风向标一般的存在。龙头股的技能面表现和成交量都会比同时刻的大盘和地块要强。 具体分…

北京健康检测小程序开发,爱自己,从体检开始

随着经济与科技的不断发展&#xff0c;人们也越来越重视自身的身体健康。面对市面上众多的体检机构与五花八门的体检产品&#xff0c;人们往往没有充足的时间进行筛选&#xff0c;好不容易选好了医院、但进行单项体检的价格较高&#xff0c;选择套餐&#xff0c;又包含了一些不…

谷歌Google广告开户是怎么收费的?

谷歌Google广告无疑是企业拓展全球视野、精准触达目标客户的强大引擎。而作为这一旅程的启航站&#xff0c;开户流程的便捷性与成本效益成为了众多企业关注的焦点。云衔科技&#xff0c;作为数字化营销解决方案与SaaS软件服务的领军者&#xff0c;正以其专业、高效的服务体系&a…

【深度学习基础】详解Pytorch搭建CNN卷积神经网络LeNet-5实现手写数字识别

目录 写在开头 一、CNN的原理 1. 概述 2. 卷积层 内参数&#xff08;卷积核本身&#xff09; 外参数&#xff08;填充和步幅&#xff09; 输入与输出的尺寸关系 3. 多通道问题 多通道输入 多通道输出 4. 池化层 平均汇聚 最大值汇聚 二、手写数字识别 1. 任务…

MySQL:SELECT list is not in GROUP BY clause 报错 解决方案

一、前言 一大早上测试环境&#xff0c;发现测试环境的MySQL报错了。 SELECT list is not in GROUP BY clause and contains nonaggregated column二、解决方案 官方文档中提到&#xff1a; 大致意思&#xff1a; 用于GROUP BY的SQL / 92标准要求满足以下条件&#xff1a; SE…

AI绘画ComfyUI-插件-面部修复,快速入门安装使用!

这期给大家分享一个插件AI绘画 ComfyUI的——Impact Pack ComfyUI也是隶属于Stable Diffusion的工作流形式的AI绘画工具。 这是一个综合节点&#xff0c;这期先介绍下这个插件中的面部修复功能 Impact Pack插件 1、下载插件 在ComfyUI管理器中安装节点&#xff0c;搜索Imp…

昇思25天学习打卡营第2天 | 张量基础

内容介绍&#xff1a;张量&#xff08;Tensor&#xff09;是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数&#xff0c;这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。 具体内容&#xff1a; 1. 导包 import numpy as np import minds…

Android 14 权限等级剖析

Android 14 权限等级剖析 Android 14 引入了新的权限等级&#xff0c;为应用程序访问敏感信息和功能提供了更细粒度的控制。了解这些新的权限等级及其应用场景对于开发人员至关重要。 1. 概述 Android 一直以来都使用权限机制来控制应用程序对系统资源和用户数据的访问。随着…

[动态规划位运算]表达式的期望值

描述 给定如下表达式&#xff1a; A0O1A1O2A2O3A3… OnAn 其中Ai(0<i<n)代表操作数&#xff0c;Oi(1<i<n)代表算子。有三类算子包括‘&’、‘|’和‘^’&#xff0c;这些算子拥有相同的计算优先级。每个算子Oi以及它后面相邻的操作数Ai&#xff0c;他们可能一…

JDK8和JDK17共存以及切换

1. 下载和安装 1.1下载安装JDK17 下载地址: https://www.oracle.com/cn/java/technologies/downloads/ 1.2安装jdk17 点击下一步 此处可以修改安装的目标位置,修改安装位置后,点击下一步 接下来及安装完成 注意事项 此时通过cmd命令java –version你会发现竟然出现了…