iframe 跨域_【梯云纵】搞定前端跨域

韦陀掌法,难陀时间善恶;梯云纵,难纵过乱世纷扰。

现在开始写代码o(╯□╰)o

什么是跨域

1.跨域的定义

广义的跨域是指一个域下对的文档或者脚本试图去请求另外一个域下的资源。

  • a链接、重定向、表单提交

  • 、、、等标签

  • background:url()、@font-face()

  • ajax 跨域请求

  • ……

狭义的跨域是指浏览器同源策略限制的一类请求场景。

同源策略

ae0708c904503a9a60b88d927508f667.png

前端跨域的主要解决方法

1.jsonp跨域

原理:动态创建 标签,然后利用 的src不受同源策略约束来跨域获取数据。

缺点:只支持get方式请求

  • 原生js实现

var script = document.createElement('script');

script.type = 'text/javascript';

// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数

script.src = 'http://www.domain2.com:8080/login?user=admin&callback=jsonPCallback';

document.head.appendChild(script);

// 前端回调执行函数

function jsonPCallback(res) {

alert(JSON.stringify(res));

}

//服务端返回如下(后端返回执行函数):

jsonPCallback({"status": true, "user": "admin"})

  • jquery实现

$.ajax({

url: 'http://www.domain2.com:8080/login',

type: 'get',

dataType: 'jsonp', // 请求方式为jsonp

jsonpCallback: "handleCallback", // 自定义回调函数名

data: {}

});

2.CORS(跨域资源共享)

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
与jsonp相比:支持所有类型的HTTP请求。但JSONP支持老式浏览器。

1.简单请求

(1) 请求方法是以下三种方法之一:

  • HEAD

  • GET

  • POST

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

  • Accept

  • Accept-Language

  • Content-Language

  • Last-Event-ID

  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

同时满足以上两个条件的就是简单请求

//简单请求,浏览器自动增加Origin字段,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

Content-Type: text/plain

Origin: http://www.domain.com

User-Agent: Mozilla/5.0

//如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器检查这个响应的头信息有没有包含Access-Control-Allow-Origin字段,没有的话,就会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

//如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://www.domain.com

//值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Credentials: true

//值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

同时,请求中也要设置

var xhr = new XMLHttpRequest();

xhr.withCredentials = true;

//Access-Control-Allow-Origin此时不能设为星号

Access-Control-Expose-Headers: FooBar

//用于拿到XMLHttpRequest对象非基本字段

2.复杂请求

//与简单请求不同的是,复杂请求多了2个字段,进行服务器预检:

Access-Control-Request-Method:该次请求的请求方式

Access-Control-Request-Headers:该次请求的自定义请求头字段

//预检成功,服务器返回的响应

//指定允许其他域名访问

'Access-Control-Allow-Origin:

//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回

'Access-Control-Allow-Credentials:true'

//预检结果缓存时间

'Access-Control-Max-Age: 1800'

//允许的请求类型

'Access-Control-Allow-Methods:GET,POST,PUT,POST'

//允许的请求头字段

'Access-Control-Allow-Headers:x-requested-with,content-type'

4.iframe 家族

1.window.name

window.name有以下特征:

  • 每个窗口都有独立的window.name与之对应;

  • 在一个窗口被关闭前,窗口载入的所有页面同时共享一个window.name,每个页面对window.name都有读写的权限;

  • window.name一直存在与当前窗口,即使是有新的页面载入也不会改变window.name的值;

  • window.name可以存储最多2M的数据,数据格式按需自定义。

原理:在页面中动态创建一个iframe页面指向另一个域,将数据赋值给ifram的window.name属性。(此时页面不能直接读取iframe的window.name),我们还需要将将iframe的src指向相同域的空白页面。之后再将iframe删除就可以了

var proxy = function(url, callback) {

var state = 0;

var iframe = document.createElement('iframe');

// 加载跨域页面

iframe.src = url;

// onload事件会触发2次,第1次加载跨域页,并留存数据于window.name

iframe.onload = function() {

if (state === 1) {

// 第2次onload(同域proxy页)成功后,读取同域window.name中数据

callback(iframe.contentWindow.name);

destoryFrame();

} else if (state === 0) {

// 第1次onload(跨域页)成功后,切换到同域代理页面

iframe.contentWindow.location = 'http://www.domain.com/aa.html';

state = 1;

}

};

document.body.appendChild(iframe);

// 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)

function destoryFrame() {

iframe.contentWindow.document.write('');

iframe.contentWindow.close();

document.body.removeChild(iframe);

}

};

// 请求跨域b页面数据

proxy('http://www.domain1.com/b.html', function(data){

alert(data);

});

window.name = 'This is domain1 data!';

2.document.domain

主域相同,子域不同的跨域应用场景。 原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

document.domain = 'domain.com';

var user = 'admin';

document.domain = 'domain.com';

// 获取父窗口中变量

alert('get js data from parent ---> ' + window.parent.user);

3.location.hash

location.hash:指的是URL的#后面的部分,比如www.domain1.com/b.html#hello 的#hello,只改变hash是不会刷新页面。 原理:通过中间页面来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

var iframe = document.getElementById('iframe');

// 向b.html传hash值

setTimeout(function() {

iframe.src = iframe.src + '#user=admin';

}, 1000);

// 开放给同域c.html的回调方法

function onCallback(res) {

alert('data from c.html ---> ' + res);

}

var iframe = document.getElementById('iframe');

// 监听a.html传来的hash值,再传给c.html

window.onhashchange = function () {

iframe.src = iframe.src + location.hash;

};

// 监听b.html传来的hash值

window.onhashchange = function () {

// 再通过操作同域a.html的js回调,将结果传回

window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));

};

5.window.postMessage

otherWindow.postMessage(message, targetOrigin, [transfer]);

window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent 消息。 该MessageEvent消息有四个属性需要注意: message 属性表示该message 的类型; data 属性为 window.postMessage 的第一个参数;origin 属性表示调用window.postMessage() 方法时调用页面的当前状态; source 属性记录调用 window.postMessage() 方法的窗口信息。 优势:页面和其打开的新窗口的数据传递、 多窗口之间消息传递、嵌套的iframe消息传递的信息传递

<iframe id="iframe" src="http://www.domain1.com/b.html" style="display:none;">iframe>

<script>

var iframe = document.getElementById('iframe');

iframe.onload = function() {

var data = {

name: 'aym'

};

// 向domain1传送跨域数据

iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain1.com');

};

// 接受domain返回数据

window.addEventListener('message', function(e) {

alert('data from domain2 ---> ' + e.data);

}, false);

script>

<script>

// 接收domain的数据

window.addEventListener('message', function(e) {

alert('data from domain ---> ' + e.data);

var data = JSON.parse(e.data);

if (data) {

data.number = 16;

// 处理后再发回domain

window.parent.postMessage(JSON.stringify(data), 'http://www.domain.com');

}

}, false);

script>

如果您不希望从其他网站接收message,请不要为message事件添加任何事件侦听器。如果您确实希望从其他网站接收message,请始终使用origin和source属性验证发件人的身份。当您使用postMessage将数据发送到其他窗口时,始终指定精确的目标origin,而不是 *

6. nginx

请看之前的文章 前端如何玩转Nginx

7. Nodejs中间件代理

中间件代理跨域相关教程,请关注冰山工作室”中间件系列教程“,敬请期待~

参考文档

阮一峰CORS 
MDN window.postMessage

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

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

相关文章

java中exception_Java中的异常 Exceptions

1. 概念exception是“exceptional event”的缩写&#xff0c;是指执行程序中发生的事件&#xff0c;破坏了程序的正常执行流程。Java 异常处理机制使程序更加健壮易于调试&#xff0c;它可以告诉程序员三个问题&#xff1a;错误的类型、位置、原因&#xff0c;帮助程序员解决错…

python异步asy_Python 异步编程之asyncio【转载】

一、协程的认识 协程&#xff08;Coroutine&#xff09;&#xff0c;也可以被称为微线程&#xff0c;是一种用户态内的上下文切换技术。 简而言之&#xff0c;其实就是通过一个线程实现代码块相互切换执行。例如&#xff1a;deffunc1():print(1) ...print(2)deffunc2():print(3…

bitcount java_Java源码解释之Integer.bitCount

Java中的Integer.bitCount(i)的返回值是i的二进制表示中1的个数。源码如下&#xff1a;public static int bitCount(int i) {// HD, Figure 5-2i i - ((i >>> 1) & 0x55555555);i (i & 0x33333333) ((i >>> 2) & 0x33333333);i (i (i >&…

git merge 冲突_卧槽!小姐姐用动画图解 Git 命令,这也太秀了吧?!

公众号关注 “GitHubDaily”设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01;大家好&#xff0c;我是小 G。在座的各位应该都知道&#xff0c;Git 作为居家必备、团队协作之利器&#xff0c;自从 Linus Torvalds 发布这款工具后&#xff0c;便一直受到各路开发者的喜爱…

android 删除文件 代码_代码审计之某系统后台存在任意删除文件

本文作者&#xff1a;霾团队交流群&#xff1a;673441920-----------------------------------------------------------前言POC镇楼&#xff01;&#xff01;&#xff01;POST 漏洞演示过程&#xff1a;首先我们利用D盾监听下我们的项目以外的目录。这里刚刚我们创建了这个文件…

ubuntu java8 java9_在Ubuntu/Debian系统上安装Java 9的方法

本文介绍在Ubuntu/Debian系统上安装Oracle Java 9的方法&#xff1a;使用webupd8team/java PPA&#xff0c;相同的PPA提供了Java 8和Java 7等旧版Java的软件包&#xff0c;如果你的应用程序需要这个&#xff0c;可以随意安装它们。要安装新版本可参考在Ubuntu 18.04系统上安装J…

websocket 压力测试_打造最强移动测试平台

笔者今年换掉了服役N年的旧手机&#xff0c;新手机12G的RAM&#xff0c;比自用的本子内存都大&#xff0c;如果只是玩游戏感觉不能完全发挥出全部机能&#xff0c;但又因为怕影响日常使用没有进行root&#xff0c;经过一番折腾&#xff0c;发现即使不root也不影响把它变成一款测…

python银行系统模拟演练_python多线程实现代码(模拟银行服务操作流程)

1.模拟银行服务完成程序代码目前&#xff0c;在以银行营业大厅为代表的窗口行业中大量使用排队(叫号)系统&#xff0c;该系统完全模拟了人群排队全过程&#xff0c;通过取票进队、排队等待、叫号服务等功能&#xff0c;代替了人们站队的辛苦。排队叫号软件的具体操作流程为&…

字符串左侧补0_(48)C++面试之最长不含重复字符的子字符串(动态规划)

// 面试题48&#xff1a;最长不含重复字符的子字符串// 题目&#xff1a;请从字符串中找出一个最长的不包含重复字符的子字符串&#xff0c;计算该最长子// 字符串的长度。假设字符串中只包含从a到z的字符。#include <vector> #include <string> #include <iost…

java udp 同一个端口实现收发_Java网络编程之UDP协议

伙伴们注意了&#xff01;小编在这里给大家送上关注福利&#xff1a;搜索微信公众号“速学Java”关注即可领取小编精心准备的资料一份&#xff01;今天我们来聊聊网络编程这部分的内容网络编程1)计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0…

java 多态_Java面向对象 —— 多态

前两天已经相继介绍了Java面向对象的三大特性之中的封装、继承&#xff0c;所以今天就介绍Java面向对象的三大特性的最后一项&#xff0c;多态~首先讲一下什么是多态&#xff0c;以及多态需要注意的细节 什么是多态&#xff1a;一个对象具备多种形态&#xff0c;也可以理解为事…

vb6 方法‘ ’作用于对象 失败_JS基础入门-对象的使用

今日背诵小纸条对象是一组属性方法的组合&#xff0c;其中可包含基本值、对象和函数对象的定义1 对象字面量var hero{name: ‘产品小姐姐’&#xff0c;age: 16&#xff0c;weapon: [ ‘头盔’, ‘靴子’, ‘盔甲 ]&#xff0c;sayHi: function ( ) {console.log( this.name ’…

无法从套接字读取更多的数据 oracle_小伙面试时被追问数据库优化,面试前如何埋点反杀?

前言周五的早高峰, 各地软件园地铁站里中出现了不少穿着长袖加绒格子衫, 背双肩电脑包的年轻码农, 现在节气正值 [ 小雪 ] , 11月的全国性突然降温 , 让经历过996摧残的猿们一出地铁站就冻的打了个激灵 , 很庆幸的告诉大家距离放年假还剩不到 37 个工作日, 要买火车票的赶紧预约…

qlineedit限制输入数字_Excel单元格限制录入,实用小技巧

在填写资料表格的时候&#xff0c;为了不防止出错&#xff0c;会在单元格中设置一些技巧&#xff0c;限制对方输入内容&#xff0c;这样可以更好的预防输入错误。那么单元格限制输入技巧是如何实现的呢&#xff1f;1、限制只能录入数字比如单元格是我们要用来填写年龄数据等数字…

java二维数组 内存分配_java中二维数组内存分配

区分三种初始化方式&#xff1a;格式一&#xff1a;数据类型[][] 数组名 new 数据类型[m][n];m:表示这个二维数组有多少个一维数组。n:表示每一个一维数组的元素有多少个。//例&#xff1a;int arr[][]new int[3][2];如下图格式二&#xff1a;数据类型[][] 数组名 new 数据类…

word公式插件_如何快速输入复杂的数学公式?这里有 3 个实用技巧

不管你是不是科研狗&#xff0c;都可能遇到过在文章中插入公式。而我们最常用的就是使用 Word 自带的公式编辑器输入&#xff0c;Word 公式可以很好地匹配文章的格式&#xff0c;自然地插入文中。有时候处理一个公式简单&#xff0c;但如果你要输入大量公式&#xff0c;键盘、鼠…

java观察者模式本质_6.[研磨设计模式笔记]观察者模式

1.定义定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并自动更新。2.解决问题——订阅报纸看起来订阅者是直接根有据打交道&#xff0c;但实际上&#xff0c;订阅者的订阅数据是被邮寄传递到报社&#xff0…

粒子群算法tsp java_粒子群算法解决TSP问题

1. 粒子群算法简介粒子群算法(particle swarm optimization&#xff0c;PSO)由Kennedy和Eberhart在1995年提出&#xff0c;属于进化算法的一种&#xff0c;是通过对模拟鸟群扑食行为设计的。基本思想&#xff1a;从随机解出发&#xff0c;通过迭代寻找最优解&#xff0c;通过适…

hive mysql性能_Hive数据库安全审计功能

【Hive数据库安全审计简介】Hive数据库安全审计是一款基于数据库通讯协议准确分析和SQL完全解析技术的数据库安全审计系统。实现了对数据库操作、访问用户及外部应用用户的审计&#xff0c;可以用于安全合规、用户行为分析、运维监控、风控审计、事件追溯等与数据库安全相关的管…

linux安装sz rz_超级好用的文件传输命令rz与sz

做生物信息经常需要在本地客户端与服务器之间进行文件的传输&#xff0c;例如将要分析的数据传到Linux服务器上&#xff0c;进行分析&#xff0c;分析结束之后将结果下载到本地windows系统进行查看。以前我们都推荐大家使用比较稳定&#xff0c;并且支持断点续传的Filezilla或者…