同源策略与解决方法

同源策略与解决方法

1.浏览器的同源策略

1.1 同源策略

同源策略(same origin policy),一种安全策略,用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。

浏览器默认两个不同的源之间是可以互相访问资源和操作 DOM 的。两个不同的源之间若是想要访问资源或者操作 DOM,就会受到同源策略的制约。

1.2 同源

同源:URL 的协议、主机、端口号相同。

解释一下协议、主机、端口号:

  • 协议:协议是定义了数据如何在计算机内和之间进行交换的规则的系统,例如 HTTP、HTTPS。
  • 主机:是已连接到一个计算机网络的一台电子计算机或其他设备。网络主机可以向网络上的用户或其他节点提供信息资源、服务和应用。使用 TCP/IP 协议族参与网络的计算机也可称为 IP 主机。
  • 端口:主机是计算机到计算机之间的通信,那么端口就是进程到进程之间的通信。

1.3 限制

同源策略的限制:

  • DOM 访问限制:DOM 和 Js 对象无法获得。同源策略限制了网页脚本(如 JavaScript)访问其他源的 DOM。这意味着通过脚本无法直接访问跨源页面的 DOM 元素、属性或方法。(防止恶意网站从其他网站窃取敏感信息)
  • Web 数据限制:Cookie、LocalStorage 和 IndexDB 无法读写。限制从其他源加载的 Web 数据(例如 XMLHttpRequest 或 Fetch API)。在同源策略下,XMLHttpRequest 或 Fetch 请求只能发送到与当前网页具有相同源的目标。(这有助于防止跨站点请求伪造(CSRF)等攻击)
  • 网络通信限制:AJAX 请求不能发送,浏览器会阻止从一个源发出的请求获取来自其他源的响应。这样做是为了确保只有受信任的源能够与服务器进行通信,以避免恶意行为。

2. 跨域解决方案

2.1 ajax 跨域请求方案 jsonp

jsonp(JSON with Padding),是 JSON 的一种 “使用模式”,可以让网页跨域读取数据,其本质是利用 script 标签的开放策略,浏览器传递 callback 参数到后端,后端返回数据时会将 callback 参数作为函数名来包裹数据,从而浏览器就可以跨域请求数据并制定函数来自动处理返回数据。

在这里插入图片描述

demo:

var script = document.createElement('script');
script.type = 'text/javascript';
// 传参callback给后端,后端返回时执行这个在前端定义的回调函数
script.src = 'http://a.qq.com/index.php?callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {alert(JSON.stringify(res));
}

优点:

  • jsonp 兼容性强,适用于所有浏览器,尤其是 IE10 以下浏览器

缺点:

  • 没有关于调用错误的处理
  • 只支持 GET 请求,不支持 POST 以及大数据量的请求,也无法拿到相关的返回头,状态码等数据
  • callback 参数恶意注入,可能会造成 xss 漏洞
  • 无法设置资源访问权限

2.2 跨域资源共享(CORS)

浏览器限制

情景:跨站请求正常发送,但是结果被浏览器拦截。

原因:浏览器将不同域的内容隔离在不同的进程中,网络进程负责下载资源并将其送到渲染进程中,但由于跨域限制,某些资源可能被阻止加载到渲染进程。如果浏览器发现一个跨域响应包含了敏感数据,它可能会阻止脚本访问这些数据,即使网络进程已经获得了这些数据。CORB 的目标是在渲染之前尽早阻止恶意代码获取跨域数据。

CORS

跨源资源共享(Cross-Origin Resource Sharing,CORS)是一种允许在受控的条件下,不同源的网页能够请求和共享资源的机制。

CORS 整个通信过程都是浏览器自动完成,浏览器一旦发现 ajax 请求跨源,就会自动在头信息中增加 Origin 字段,用来说明本次请求来自哪个源(协议+域名+端口)。因此,实现 CORS 通信的关键是服务器,需要服务器配置 Access-Control-Allow-Origin 头信息。
基本思想:

  • 服务器在响应中提供一个标头(HTTP 头),指示哪些源被允许访问资源。
  • 浏览器在发起跨域请求时会先发送一个预检请求(OPTIONS 请求)到服务器,服务器通过设置适当的 CORS 标头来指定是否允许跨域请求,并指定允许的请求源、方法、标头等信息。

CORS 的请求根据是否会触发 OPTIONS 请求,分为两类:

  • 简单请求:不触发 CORS 的请求
  • 预检请求:在正式通信之前,增加一次 OPTIONS 查询请求。

简单请求

需要满足的条件:

  • HTTP 方法限制:只能使用 GET、HEAD、POST 这三种 HTTP 方法之一。如果请求使用了其他 HTTP 方法,就不再被视为简单请求。
  • 自定义标头限制:请求的 HTTP 标头只能是以下几种常见的标头:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(仅限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)。HTML 头部 header field 字段:DPR、Download、Save-Data、Viewport-Width、WIdth。如果请求使用了其他标头,同样不再被视为简单请求。
  • 请求中没有使用 ReadableStream 对象。
  • 不使用自定义请求标头:请求不能包含用户自定义的标头。
  • 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问

预检请求

  • 预检请求:在正式通信之前,增加一次 OPTIONS 查询请求。服务器通过了 预检请求,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样,会有一个 Origin 头信息字段。服务器的回应,也都会有一个 Access-Control-Allow-Origin 头信息字段。

第一个类型为 preflight 就是预检请求:

在这里插入图片描述

查看预检请求的请求头数据:

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

OPTIONS 请求头中的特殊字段:

  • ccess-Control-Request-Method:该字段是必须的,用来列出浏览器的 CORS 请求会用到哪些 HTTP 方法。
  • Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段。即告知服务器,实际请求将携带的自定义请求首部字段。

查看预检请求的响应头数据:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

OPTIONS 响应头中的特殊字段:

  • Access-Control-Allow-Credentials(可选):值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中。设为 true,即表示服务器明确许可,前端也需要设置 withCredentials,Cookie 可以包含在请求中,一起发给服务器。这个值也只能设为 true,如果服务器不要浏览器发送 Cookie,删除该字段即可。
  • 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-Methods:表明服务器允许客户端使用什么方法发起请求
  • Access-Control-Allow-Origin:(必须):表示可以请求的数据,可以设置为* 符号,表示允许任意跨源请求。
  • Access-Control-Allow-Headers:将实际请求所携带的首部字段告诉服务器

OPTIONS 请求的更多信息,可参考官方文档

在这里插入图片描述

优点与缺点

优点:

  • 支持所有类型的 HTTP 请求,功能完善。
  • 通过 onerror 事件监听进行调用错误处理;
  • 通过 Access-Control-Allow-Origin 进行资源访问授权。

缺点:

  • 目前主流浏览器(IE10 及以上)都支持 CORS,但 IE8 和 IE9 需要使用 XDomainRequest 对象进行兼容,IE7 及以下浏览器不支持。

2.3 服务器代理

后端进行代理中转请求至服务器端,然后将获取的数据返回给前端。

外网前端页面无法访问内网接口,配置代理接口允许前端页面访问,并中转内网接口,则外网前端页面可以跨域访问内网接口。

比如配置 Nginx,将接收到的请求转发到内网:

    server{#如果是静态文件,直接指向目录location / {root   html;index  index.html index.htm;}# 如果是动态应用,用proxy_pass转发一下location ~ ^/api/(.*?)$ {proxy_pass  http://127.0.0.1:8080/api/$1?$args;}}

优点:

  • 前端无需进行任何改变

缺点:

  • 后端需要一定工作量

2.4 前端跨域

前端跨域通信是指浏览器中两个不符合同源策略的前端页面进行通信。

2.4.1 document.domain+iframe

仅适用于主域相同,子域不同的前端通信跨域场景。

核心点:

  • A 嵌套 B
  • 将 document.domain 指向主域名

页面 A:

<!-- A页面 http://a.qq.com/a.html -->
<iframe id="iframe" src="http://b.qq.com/b.html"></iframe>
<script>document.domain = 'qq.com';var windowB = document.getElementById('iframe').contentWindow;alert('B页面的user变量:' + windowB.user);
</script>

页面 B:

<!-- B页面 http://b.qq.com/b.html -->
<script>document.domain = 'qq.com';var user = 'saramliu';
</script>

2.4.2 location.hash+iframe

利用 url 的 hash 值改变但不刷新页面的特性,实现简单的前端跨域通信。

受到浏览器安全机制的限制,A 嵌套 B,A 可以修改 B 的 hash 值,但 B 不能修改 A 的 Hash 值,需要一个与 A 同源的页面来中转。

A 页面:

<!-- A页面 http://a.qq.com/a.html -->
<iframe id="iframe" src="http://b.qq1.com/b.html"></iframe>
<script>// 监听c.html传来的hash值window.onhashchange = function () {alert('B页面传递数据:' + location.hash.substring(1));};
</script>

B 页面:

<!-- B页面 http://b.qq1.com/b.html -->
<iframe id="iframe" src="http://a.qq.com/c.html"></iframe>
<script>// 向c.html传递hash值var iframe = document.getElementById('iframe');setTimeout(function () {iframe.src = iframe.src + '#user=saramliu';}, 1000);
</script>

中转页面:

<!-- C页面 http://a.qq.com/c.html -->
<script>// 监听b.html传来的hash值window.onhashchange = function () {// 操作同域a.html的hash值,传递数据window.parent.parent.location.hash = window.location.hash.substring(1);};
</script>

优点:

  • 可以解决主域不同的前端通信跨域问题。
  • hash 改变,页面不会刷新。

缺点:

  • 受部分浏览器安全机制限制,需要额外的同源中转页面,且中转页面需要 js 逻辑来修改 hash 值。
  • 通信数据类型及长度均受限,且数据外显在 url 上,存在一定安全风险。

2.4.3 window.name+iframe

window.name 属性在不同页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

A 嵌套 B,B 将要传递的数据附加到 window.name 上,然后跳转到与 A 同域名的 C,A 和 C 满足同源策略,A 可与获取到 C 的 window.name。

A

<!-- A页面 http://a.qq.com/a.html -->
<iframe id="iframe" src="http://b.qq1.com/b.html"></iframe>
<script>var state = 0;var iframe = document.getElementById('iframe');iframe.onload = function () {if (state === 1) {// 第2次onload成功后,读取同域window.name中数据alert(iframe.contentWindow.name);} else if (state === 0) {// 第1次onload成功后state = 1;}};
</script>

B:

<!-- B页面 http://b.qq1.com/b.html -->
<script>window.name = '这里是B页面!';window.location = 'http://a.qq.com/c.html'; // 跳转到与A同源的C
</script>

优点:

  • 通信数据类型不受限,且长度可达 2MB。

缺点:

  • 需要额外的同源中转页面,但中转页可以为空白页。

2.4.4 postMessage

postMessage 是 HTML5 XMLHttpRequest Level2 中的 API,是一种安全的跨域通信方法,且是为数不多可以跨域操作的 window 属性之一,它通常用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递。
  • 多窗口之间消息传递。
  • 页面与嵌套 iframe 消息传递。

A 获得 B 的 window 对象后,A 调用 postMessage 方法发送一个个 MessageEvent 消息。B 通过监听 message 事件即可获取 A 传递的数据。

A:

<iframe id="iframe" src="http://b.qq1.com/b.html"></iframe>
<script>var iframe = document.getElementById('iframe');iframe.onload = function () {var data = { meesage: '这里是A页面发的消息' };var url = 'http://b.qq1.com/b.html'; // 向B页面发送消息iframe.contentWindow.postMessage(JSON.stringify(data), url);};window.addEventListener('message', function (e) {alert('B页面发来消息:' + JSON.parse(e.data));});
</script>

B:

<!-- B页面 http://b.qq1.com/b.html -->
<script>window.addEventListener('message',function (e) {alert('A页面发来消息:' + JSON.parse(e.data));var data = { meesage: '这里是B页面发的消息' };var url = 'http://a.qq.com/a.html';window.parent.postMessage(JSON.stringify(data), url);},false);
</script>

优点:

  • 可以解决多种类型的前端跨域通信问题。

缺点:

  • 兼容性方面相对差一点,IE8 及以下浏览器不支持该方法,IE9 只支持 postMessage 传递 string 类型的数据,而标准的 postMessage 消息数据可以是任何类型。

参考文档

  • 同源策略(same origin policy)

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

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

相关文章

集合框架-(Collection/Map)

1.单列集合 1.1基础概要 集合中存储的是对象的地址信息&#xff0c;想要输出对象的信息&#xff0c;需要在具体的类中重写toString&#xff08;&#xff09;方法 Collection代表单列集合&#xff0c;每个元素数据只包含一个值 List集合&#xff1a;添加的元素可以是有序、可…

【第1章 数据结构概述】

目录 一. 基本概念 1. 数据、数据元素、数据对象 2. 数据结构 二. 数据结构的分类 1. 数据的逻辑结构可分为两大类&#xff1a;a. 线性结构&#xff1b;b. 非线性结构 2. 数据的存储结构取决于四种基本的存储方法&#xff1a;顺序存储、链接存储、索引存储、散列存储 3. …

uni-app中使用iconfont彩色图标

uni-app中使用iconfont彩色图标 大家好&#xff0c;今天我们来学习一下uni-app中使用iconfont彩色图标&#xff0c;好好看&#xff0c;好好学&#xff0c;超详细的 第一步 首先&#xff0c;从iconfont官网&#xff08;iconfont-阿里巴巴矢量图标库&#xff09;选择自己需要的图…

从零构建深度学习推理框架-11 Resnet

op和layer结构 在runtime_ir.cpp中&#xff0c;我们上一节只构建了input和output&#xff0c;对于中间layer的具体实现一直没有完成&#xff1a; for (const auto& kOperator : this->operators_) {if (kOperator->type "pnnx.Input") {this->input_o…

Soul涉赌?元宇宙“皮囊”绷不住走样的“灵魂社交”

“软色情”、“杀猪盘”之后&#xff0c;陌生人社交平台Soul又多了一张“涉赌”标签。 8月初&#xff0c;视频媒体青蜂侠Bee报道称&#xff0c;Soul平台内游戏“星际庄园”名为“种地”&#xff0c;但用户充值种“水果”、平台发起概率抽奖、奖励转手可场外变现的玩法暗藏赌博…

DNS 协议都没听过?你配做开发?

一、什么是DNS协议&#xff1f; DNS协议是一种用于将域名转换为IP地址的分布式命名系统。它通过将用户提供的域名映射到相应的IP地址&#xff0c;实现了互联网上资源的定位和访问。DNS协议采用了层次化的域名结构&#xff0c;使得域名之间可以建立逻辑上的关联。 二、DNS解析过…

新建Spring Boot项目

使用IDEA 来创建: 文件-新建-项目 填写项目元数据 选择依赖项 此处可以先选 web-spring web 关于这些依赖项&#xff0c;更多可参考&#xff1a; IDEA创建Spring boot项目时各依赖的说明&#xff08;Developer Tools篇&#xff09;[1] 项目结构介绍 展开项目&#xff0c;此时…

跨站请求伪造(CSRF)

文章目录 渗透测试漏洞原理跨站请求伪造&#xff08;CSRF&#xff09;1. CSRF概述1.1 基本概念1.1.1 关键点1.1.2 目标 1.2 CSRF场景1.2.1 银行账户转账1.2.2 构造虚假网站1.2.3 场景建模1.2.4 实验 1.3 CSRF类别1.3.1 POST方式 1.4 CSRF验证1.4.1 CSRF Poc generator 1.5 XSS与…

Python爬虫(十六)_JSON模块与JsonPath

数据提取之JSON与JsonPATH JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;它是的人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景&#xff0c;比如网站前台与后台之间的数据交互。 JSON和XML的比较可谓不相…

Day50|动态规划part11:188.买卖股票的最佳时机IV、123. 买卖股票的最佳时机III

188. 买卖股票的最佳时机IV leetcode链接&#xff1a;188 题「买卖股票的最佳时机 IVopen in new window」 视频链接&#xff1a;动态规划来决定最佳时机&#xff0c;至多可以买卖K次&#xff01;| LeetCode&#xff1a;188.买卖股票最佳时机4 给你一个整数数组 prices 和一…

用反射实现自定义Java对象转化为json工具类

传入一个object类型的对象获取该对象的class类getFields方法获取该类的所有属性对属性进行遍历&#xff0c;并且拼接成Json格式的字符串&#xff0c;注意&#xff1a;通过属性名来推断方法名获取Method实例通过invoke方法调用 public static String objectToJsonUtil(Object o…

线程安全-搞清synchronized的真面目

多线程编程中&#xff0c;最难的地方&#xff0c;也是最重要的一个地方&#xff0c;还是一个最容易出错的地方&#xff0c;更是一个特别爱考的地方&#xff0c;就是线程安全问题。 万恶之源&#xff0c;罪魁祸首&#xff0c;多线程的抢占式执行,带来的随机性. 如果没有多线程,此…

可拖动表格

支持行拖动&#xff0c;列拖动 插件&#xff1a;sortablejs UI: elementUI <template><div><hr style"margin: 30px 0;"><div><!-- 数据里面要有主键id&#xff0c; 否则拖拽异常 --><h2 style"margin-bottom: 30px&qu…

python遍历文件夹下的所有子文件夹,并将指定的文件复制到指定目录

python遍历文件夹下的所有子文件夹&#xff0c;并将指定的文件复制到指定目录 需求复制单个文件夹遍历所有子文件夹中的文件&#xff0c;并复制代码封装 需求 在1文件夹中有1&#xff0c;2两个文件夹 将这两个文件夹中的文件复制到 after_copy中 复制单个文件夹 # coding: ut…

【跨域异常】

想在前端使用vue获取后端接口的数据&#xff0c;但是报了跨域异常&#xff0c;如下图所示。 一种解决的方式是&#xff0c;在后端Controller接口上加上CrossOrigin&#xff0c;从后端解决跨域问题。 还要注意前端请求的url要加上协议&#xff0c;比如http://

Excel:通过Lookup函数提取指定文本关键词

函数公式&#xff1a;LOOKUP(9^9,FIND($G 2 : 2: 2:G 6 , C 2 ) , 6,C2), 6,C2),G 2 : 2: 2:G$6) 公式解释&#xff1a; lookup第一参数为9^9&#xff1a;代表的是一个极大值的数据&#xff0c;查询位置里面最接近这一个值的数据&#xff1b;lookup第二参数用find函数代替&am…

80. 删除有序数组中的重复项 II

【中等题】 题目&#xff1a; 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额…

string类中的一些问题

前言&#xff1a;C中的string类是继承C语言的字符数组的字符串来实现的&#xff0c;其中包含许多C的字符串的相关知识的同时&#xff0c;也蕴含很多的类与对象的相关知识&#xff0c;在面试中&#xff0c;面试官总喜欢让学生自己来模拟实现string类&#xff0c;最主要是实现str…

RK3568 安卓源码编译

一.repo安卓编译工具 项目模块化/组件化之后各模块也作为独立的 Git 仓库从主项目里剥离了出去&#xff0c;各模块各自管理自己的版本。Android源码引用了很多开源项目&#xff0c;每一个子项目都是一个Git仓库&#xff0c;每个Git仓库都有很多分支版本&#xff0c;为了方便统…

request+python操作文件导入

业务场景&#xff1a; 通常我们需要上传文件或者导入文件如何操作呢&#xff1f; 首先通过f12或者通过抓包查到请求接口的参数&#xff0c;例如&#xff1a; 图中标注的就是我们需要的参数&#xff0c;其中 name是参数名&#xff0c;filename是文件名&#xff0c;Content-Type是…