浏览器跨域访问限制

article/2025/10/6 3:34:51

一.什么是跨域

广义的跨域:
(1) 资源跳转:A链接、重定向、表单提交
(2) 资源嵌入:<link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
(3) 脚本请求:js发起的ajax请求、dom和js对象的跨域操作等

其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。

二.什么是浏览器跨域限制?本质是什么?

所谓浏览器跨域限制,其实是为了数据安全的考虑由Netscape提出来限制浏览器访问跨域数据的策略。
这是一种约定,正式叫法为“浏览器同源策略”,目前已经在大多数浏览器中支持。

本质上,所谓浏览器同源策略,即:不允许浏览器访问跨域的Cookie,ajax请求跨域接口等
也就是说,凡是访问与自己不在相同域的数据或接口时,浏览器都是不允许的。

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A 网站是一家银行,用户登录以后,A 网站在用户的机器上设置了一个 Cookie,包含了一些隐私信息(比如存款总额)。用户离开 A 网站以后,又去访问 B网站,如果没有同源限制,B 网站可以读取 A 网站的 Cookie,那么隐私信息就会泄漏。更可怕的是,Cookie往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,同源政策是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
随着互联网的发展,同源政策越来越严格。目前,如果非同源,共有三种行为受到限制。

1.无法获取非同源网页的 cookie、localstorage 和 indexedDB。
2.无法访问非同源网页的 DOM (iframe)(DOM:Document Object Mode:文档对象模型)。
3.无法向非同源地址发送 AJAX 请求 或 fetch 请求(可以发送,但浏览器拒绝接受响应)。


Ajax 的同源策略主要是为了防止 CSRF(跨站请求伪造) 攻击,如果没有 AJAX 同源策略,相当危险,我们发起的每一次 HTTP请求都会带上请求地址对应的 cookie,那么可以做如下攻击:
1.用户登录了自己的银行页面 mybank.com,mybank.com向用户的cookie中添加用户标识。
2.用户浏览了恶意页面evil.com。执行了页面中的恶意AJAX请求代码。
3. evil.com向http://mybank.com发起AJAX
HTTP请求,请求会默认把http://mybank.com对应cookie也同时发送过去。
4.银行页面从发送的cookie中提取用户标识,验证用户无误,response中返回请求数据。此时数据就泄露了。
5.而且由于Ajax在后台执行,用户无法感知这一过程。

DOM同源策略也一样,如果 iframe 之间可以跨域访问,可以这样攻击:

1.做一个假网站,里面用iframe嵌套一个银行网站 mybank.com。
2.把iframe宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。
3.这时如果用户输入账号密码,我们的主网站可以跨域访问到http://mybank.com的dom节点,就可以拿到用户的输入了,那么就完成了一次攻击。

最常见的例子:对于前后端完全分离的Web项目,前端页面通过rest接口访问数据时,会出现如下问题:

  • 不允许发送POST请求:在发送POST请求之前会发送OPTIONS请求,HTTP响应状态码为403(Forbidden)。
  • 允许发送GET请求:HTTP响应状态码为200,但是不能读取服务器返回的数据。

同时,在浏览器(firefox调试)控制台可以看到如下提示:

已拦截跨源请求:同源策略禁止读取位于 
http://host:port/path 的远程资源。(
原因:CORS 头缺少 'Access-Control-Allow-Origin')。

对URL来说,所谓的“同源”包含3个要素:协议相同,主机名(域名或IP地址,IP地址则看做是根域名)相同,端口相同。
在这里插入图片描述

举例来说,对于http://test.chench.org/page.html这个地址,以下情况被认为是同源与不同源的:
在这里插入图片描述

三.为什么会存在浏览器跨域限制?

既然目前各主流浏览器都存在跨域限制,那么为什么一定要存在这个限制呢?如果没有跨域限制会出现什么问题?

浏览器同源策略的提出本来就是为了避免数据安全的问题,即:限制来自不同源的“document”或脚本,对当前“document”读取或设置某些属性。
如果没有这个限制,将会出现什么问题?不妨看一下几个情形:

  • 可能a.com的一段JavaScript脚本,在b.com未曾加载此脚本时,也可以随意涂改b.com的页面。
  • 在浏览器中同时打开某电商网站(域名为b.com),同时在打开另一个网站(a.com),那么在a.com域名下的脚本可以读取b.com下的Cookie,如果Cookie中包含隐私数据,后果不堪设想。
  • 因为可以随意读取任意域名下的Cookie数据,很容易发起CSRF攻击。
(CSRF攻击:跨站请求伪造(英語:Cross-site request forgery),
也被称为one-click attack 或者session riding,通常缩写为CSRF 或者XSRF, 
是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。)
可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。C
SRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,
虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

在这里插入图片描述

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:1.登录受信任网站A,并在本地生成Cookie。2.在不登出A的情况下,访问危险网站B。看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

所以,同源策略是浏览器安全的基础,同源策略一旦出现漏洞被绕过,也将带来非常严重的后果,很多基于同源策略制定的安全方案都将失去效果。

四.对于浏览器来说,哪些资源(操作)会受到同源策略的限制?

对于浏览器来说,除了DOM,Cookie,XMLHttpRequest会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。
最常见的一些插件如Flash,Java Applet,Silverlight,Google Gears等都有自己的控制策略。
另外,存储在浏览器中的数据,如LocalStorage和IndexedDB,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操作。

五.浏览器跨域限制会带来什么问题?

随着互联网的发展,对用户体验的要求越来越高,AJAX应用也就越发频繁,AJAX的本质就是XMLHttpRequest。
但XMLHttpRequest受到同源策略的约束,所以不能跨域访问资源,这与我们的期望是相违背的。

六.解决浏览器跨域限制的方法有哪些?如何选择合适的方案?

1. JSONP
在浏览器中,<script>,<img>,<iframe>,<link>等标签都可以跨域加载资源,而不受同源策略的限制。
这些带"src"属性的标签每次加载时,实际上是由浏览器发起了一次GET请求。
不同于XMLHttpRequest的是,通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读写返回的内容。

  • <script src="..."></script>标签嵌入跨域脚本。

  • <link rel="stylesheet" href="...">标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type消息头。不同浏览器有不同的限制。

  • <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,…

  • <video> 和<audio>嵌入多媒体资源。

  • <object>, <embed><applet>的插件。

  • @font-face引入的字体。一些浏览器允许跨域字体(ross-origin fonts),一些需要同源字体(same-origin fonts)。

  • <frame><iframe>载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。

JSONP就是利用这个特性,通过javascript标签加载资源的方式请求跨域接口数据,间接绕开了浏览器同源策略的限制。

具体来说,就是在DOM中通过动态创建javascript标签,并给标签设置src属性,在访问请求参数中传递需要回调的函数名;
同时,服务端在响应jsonp请求时,将数据作为请求参数指定的客户端回调函数参数作为返回值,这样对于客户端来说服务器的响应数据其实是回调函数的参数,是javascipt对象,而不是字符串,因此避免了使用JSON.parse的步骤。

2. CORS(Cross-Origin Resource Sharing)
CORS是一个解决浏览器跨域限制的W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
具体来说,根据CORS标准定义,服务端需要在浏览器的跨域请求响应中包含指定消息头,浏览器根据响应消息头知道是否可以访问跨域资源。

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

服务器端配置
CORS常用的配置项有以下几个:

  • Access-Control-Allow-Origin(必含) – 允许的域名,只能填 *(通配符)或者单域名。
  • Access-Control-Allow-Methods(必含) – 这允许跨域请求的 http 方法(常见有POST、GET、OPTIONS)。
  • Access-Control-Allow-Headers(当预请求中包含 Access-Control-Request-Headers时必须包含) – 这是对预请求当中 Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。
  • Access-Control-Allow-Credentials(可选) –表示是否允许发送Cookie,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项XmlHttpRequest 对象当中的 withCredentials 属性应保持一致,即 withCredentials为true时该项也为true;withCredentials 为false时,省略该项不写。反之则导致请求失败。
  • Access-Control-Max-Age(可选) – 以秒为单位的缓存时间。在有效时间内,浏览器无须为同一请求再次发起预检请求。

CORS 跨域的判定流程

  • 浏览器先根据同源策略对前端页面和后台交互地址做匹配,若同源,则直接发送数据请求;若不同源,则发送跨域请求。
  • 服务器收到浏览器跨域请求后,根据自身配置返回对应文件头。若未配置过任何允许跨域,则文件头里不包含Access-Control-Allow-origin 字段,若配置过域名,则返回 Access-Control-Allow-origin + 对应配置规则里的域名的方式
  • 浏览器根据接受到的 响应头里的 Access-Control-Allow-origin字段做匹配,若无该字段,说明不允许跨域,从而抛出一个错误;若有该字段,则对字段内容和当前域名做比对,如果同源,则说明可以跨域,浏览器接受该响应;若不同源,则说明该域名不可跨域,浏览器不接受该响应,并抛出一个错误。

上面说到的两种类型的报错,控制台输出是不一样的:

  • 服务器允许跨域请求,但是 Origin 指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含 Access-Control-Allow-Origin 字段,就知道出错了,从而抛出一个错误,被 XMLHttpRequest的onerror 回调函数捕获。注意,这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是200。
<!--控制台返回结果-->XMLHttpRequest cannot load http://localhost/city.json.The 'Access-Control-Allow-Origin' header has a value 'http://segmentfault.com' that is not equal to the supplied origin. Origin 'http://www.zhihu.com' is therefore notallowed access.
  • 服务器不允许任何跨域请求
<!--控制台返回结果-->
XMLHttpRequest cannot load http://localhost/city.json.
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://www.zhihu.com' is therefore not allowed access.

简单请求
实际上浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

简单请求是指满足以下条件的(一般只考虑前面两个条件即可):

  1. 使用 GET、POST、HEAD 其中一种请求方法。

  2. HTTP的头信息不超出以下几种字段:

    Accept 
    Accept-Language 
    Content-Language 
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 
    
  3. 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;

  4. XMLHttpRequestUpload对象可以使用 XMLHttpRequest.upload 属性访问。 请求中没有使用 ReadableStream 对象。

对于简单请求,浏览器直接发起 CORS 请求,具体来说就是服务器端会根据请求头信息中的 origin 字段(包括了协议 + 域名 + 端口),来决定是否同意这次请求。

如果 origin 指定的源在许可范围内,服务器返回的响应,会多出几个头信息字段:

Access-Control-Allow-Origin: http://xxx.xxx.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

非简单请求
非简单请求时指那些对服务器有特殊要求的请求,比如请求方法是 putdelete,或者 content-type 的类型是 application/json。其实简单请求之外的都是非简单请求了。

非简单请求的 CORS 请求,会在正式通信之前,使用 OPTIONS 方法发起一个预检(preflight)请求到服务器,浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
在这里插入图片描述
下面是一个预检请求的头部:

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样了。

3. WebSocket
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。
该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

4. 解决方法总结
在这里插入图片描述
https://www.cnblogs.com/nuccch/p/7466709.html

https://juejin.im/post/5cad99796fb9a068ab40a29a


http://chatgpt.dhexx.cn/article/G9FxAVjT.shtml

相关文章

Django 多方式实现跨域访问

一、什么是跨域 1.1 跨越介绍 跨域&#xff0c;是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器对JavaScript实施的安全限制。 这里说明一下&#xff0c;无法跨域是浏览器对于用户安全的考虑&#xff0c;如果自己写个没有同源策略的浏览…

Flask中跨域访问的实现

在我们访问不同的服务器时&#xff0c;就会涉及到了跨域的问题。因为不同域名之间是无法进行交流的&#xff0c;然后跨域就打破了这种规则的限制。说起Flask中的跨域&#xff0c;就不得不提到CORS组件了&#xff0c;相信大家在其它框架中也见过了它的身影。下面我们就跨域问题和…

Tomcat设置允许跨域访问

开发React项目时前端通过axios向后端代码发起请求调试的时候由于后端代码运行在8080端口而React项目运行在3000端口导致浏览器的同源策略禁止跨域请求&#xff0c;因此需修改Tomcat配置文件web.xml以开放跨域访问。 在tomcat的web.xml文件末尾加上&#xff1a; <filter>…

express 允许跨域访问

设置Express const express require(express) const bodyParser require(body-parser)const app express() // 处理参数 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));// 设置允许跨域访问该服务 app.all(*, function (req, res, nex…

tomcat 设置允许跨域访问

既然想到使用tomcat进行跨域的设置&#xff0c;而不使用在项目中设置header来解决&#xff0c;说明你也是tomcat 下的资源需要做跨域处理吧&#xff1f;这也是一个统一的允许跨域设置&#xff0c;tomcat下的所有请求都将放开&#xff0c;请注意。 具体步骤&#xff1a; 1.首先…

Chrome浏览器 设置跨域访问

由于浏览器的安全策略&#xff0c;不同域名的访问会被限制&#xff0c;导致不能访问 chorme或者360都可以使用下列设置来解决这个问题&#xff1a; &#xff08;1&#xff09;在电脑上新建一个目录&#xff0c;例如&#xff1a;C:\MyChromeEnvUserData &#xff08;2&#x…

tomcat9配置允许跨域访问

目录 一、问题描述二、解决办法三、程序截图 一、问题描述 最近在用Tomcat9最新版本部署程序的时候&#xff0c;发现其他服务访问我的静态资源的时候出现了跨域访问&#xff0c;结果很明显被拦截了&#xff0c;之前的文章介绍了Tomcat8.5的跨域配置&#xff0c;但是研究发现&a…

html的页面怎样直接跨域访问,【HTML】iframe跨域访问问题

概述 本地同一浏览器访问本地HTML文件和访问服务器端HTML文件,本地Iframe没有自适应高度,而服务器端的Ifrane自适应了高度。 1.问题重现: Chrome 版本 41.0.2272.101 (64-bit) OS:Win8.1 Chrome访问服务器端HTML文件呈现的结果 Chrome访问本地HTML文件呈现的结果 本地访问的…

vue跨域访问

vue跨域访问的问题&#xff08;基于允许跨域访问的前提&#xff09; 找到“ vue.config.js"&#xff0c;有些不是vue.config.js命名&#xff0c;也就是找到重写路径的js文件。重写一下自己要替换的路径&#xff0c;在原有基础上加一个 新建一个dev.js文件内容如下&#…

关于跨域访问

1 概念 2 案例 3 解决 4 实现 5 什么是跨域问题 示意图 1 概念 跨域访问&#xff0c;是指从一个域名的网页去请求另一个域名的资源。比如从 www.baidu.com 页面去请求 ww w.google.com 的资源。 但是一般情况下不能这么做跨域访问&#xff0c;因为有浏览器的 “ 同源策略…

什么是跨域?如何实现跨域访问?

跨域是指不同域名之间相互访问。 JavaScript同源策略的限制&#xff0c;A域名下的JavaScript无法操作B或是C域名下的对象 实现&#xff1a; 1、JSONP跨域&#xff1a;利用script脚本允许引用不同域下的js实现的&#xff0c;将回调方法带入服务器&#xff0c;返回结果时回调 2、…

跨域访问

跨域访问是什么 同源策略 1995年&#xff0c;同源政策由Netscape公司引人浏览器。目前&#xff0c;所有刘览器都实行这个政策。同源政策的目的&#xff0c;是为了保证用户信息的安全&#xff0c;防止恶意的网站窃取数据。随着互联网的发展&#xff0c;“同源政策”越来越严格…

朴素贝叶斯分类器python_python实现高斯朴素贝叶斯分类器

在这篇文章中,我们将使用我最喜欢的机器学习库scikit-learn在Python中实现朴素贝叶斯分类器。接下来,我们将使用经过训练的朴素贝叶斯(监督分类法)模型来预测人口收入。 在朴素贝叶斯分类器的文章中我们讨论了贝叶斯定理,我们希望你对贝叶斯定理的基础知识有一定的了解,如果…

贝叶斯分类器(matlab)

目标 下表由雇员数据库的训练数据组成。数据已泛化。例如&#xff0c;age“3135”表示年龄在31~35之间。对于给定的行&#xff0c;count表示department、status、age和salary在该行具有给定值的元组数。 DepartmentStatusAgeSalaryCountSalesSenior31-3546K-50K30Salesjunior…

Python实现朴素贝叶斯分类器

朴素贝叶斯分类器 文章目录 朴素贝叶斯分类器一、贝叶斯分类器是什么&#xff1f;贝叶斯判定准则朴素贝叶斯分类器举个栗子 二、相关代码1.数据处理2.生成朴素贝叶斯表&#xff08;字典&#xff09;关于如何判断属性的连续或离散性 根据朴素贝叶斯表计算预测标签 总结 一、贝叶…

贝叶斯分类器 (下)

目录 错误率与风险 朴素贝叶斯分类器 平滑&#xff1a;拉普拉斯修正 半朴素贝叶斯分类器 错误率与风险 书接上回&#xff0c;我们讲到最大后验概率&#xff0c;我们期望把概率最大时对应的属性&#xff0c;当做它最终的结果。我们自然也会思考&#xff0c;这样做准不准&…

贝叶斯分类器算法原理

目录 1.1&#xff0c;什么是朴素贝叶斯 1.2&#xff0c;极大似然估计 1.3&#xff0c;朴素贝叶斯分类器 1.4&#xff0c;朴素贝叶斯算法就程 1.5&#xff0c;朴素贝叶斯的优缺点 1.1&#xff0c;什么是朴素贝叶斯 在所有的机器学习分类算法中&#xff0c;朴素贝叶斯和其他…

【贝叶斯分类3】半朴素贝叶斯分类器

文章目录 1. 朴素贝叶斯分类器知识回顾1.1 类别&#xff0c;特征1.2 风险&#xff0c;概率1.3 类条件概率 2. 半朴素贝叶斯分类器学习笔记2.1 引言2.2 知识卡片2.3 半朴素贝叶斯分类器2.4 独依赖估计2.4.1 简介2.4.2 SPODE(超父独依赖估计)2.4.3 AODE(平均独依赖估计)2.4.4 TAN…

【贝叶斯分类2】朴素贝叶斯分类器

文章目录 1. 贝叶斯决策论回顾1.1 分类原理1.2 贝叶斯分类器1.3 P(c|x)1.4 计算公式1.5 极大似然估计 2. 朴素贝叶斯分类器学习笔记2.1 引言2.2 知识卡片2.3 朴素贝叶斯分类器2.4 拉普拉斯平滑 3. 朴素贝叶斯分类器拓展3.1 数据处理3.2 收集其他资料 1. 贝叶斯决策论回顾 1.1 …

朴素贝叶斯分类器

前知识了解&#xff1a; 贝叶斯决策论是概率框架下实施决策的基本方法。 贝叶斯定理&#xff1a; 贝叶斯定理是由果溯因的思想&#xff0c;当知道某件事情的结果后&#xff0c;由结果推断出这件事是由各种原因导致的概率为多少。极大似然估计&#xff1a; 朴素贝叶斯分类器…