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 >&…

python自定义全局异常_如何在python中进行全局异常捕获

使用sys.excepthook函数进行全局异常的获取。 首先定义异常处理函数&#xff0c; 并使用该函数接收系统异常信息。 import wx import sys class TestFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, test) btn wx.Button(self, -1, test) btn.Bind(w…

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

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

freebsd java 能用吗_在FreeBSD 4.9下安装JAVA环境

导读&#xff1a;资源下载地址&#xff1a;1.http://www.sun.com/softwarre/java2/download.html2.http://ftp.csie.chu.edu.tw/FreeBSD/distfiles/openmotif/3.http://ameba.sc-uni.ktu.lt/pub/FreeBSD/4.http://www.wormwang.net/mirrors/java/一、以下的包要先下载放到各自的…

python中exec是什么意思_Python中的进程分支fork和exec详解

在python中,任务并发一种方式是通过进程分支来实现的.在linux系统在,通过fork()方法来实现进程分支. 1.fork()调用后会创建一个新的子进程,这个子进程是原父进程的副本.子进程可以独立父进程外运行. 2.fork()是一个很特殊的方法,一次调用,两次返回. 3.fork()它会返回2个值,一个…

java冒泡排序原理_冒泡排序原理及其java实现

冒泡排序原理&#xff1a;临近的数字两两进行比较&#xff0c;按照从小到大或者从大到小的顺序进行交换&#xff0c;这样外层循环每循环一次&#xff0c;都会把一个数的顺序排好(从小到大的话每次都会把上回剩余的数据最大的放在剩余数的最后面&#xff0c;反之则是最小的放剩余…

java holder_java.sql.SQLException: connection holder is null

错误信息2017-11-15 14:53:16.931 [ ] ERROR com.hzcf.flagship.web.AssetPlanController 126 :### Error updating database. Cause: java.sql.SQLException: connection holder is null### Cause: java.sql.SQLException: connection holder is null; uncategorized SQLExcep…

java signed_如何从java中的字节读取signed int?

我有一个规范读取接下来的两个字节是signed int.要在java中读取我有以下内容当我使用以下代码在java中读取signed int时,我得到值65449计算无符号的逻辑int a (byte[1] & 0xff) <<8int b (byte[0] & 0xff) <<0int c ab我认为这是错误的,因为如果我和0xff我…

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…

jp摩根的人都在学python么_摩根大通已要求所有资管部门员工必须学习编程

当代最具竞争力的技能是什么&#xff1f;摩根大通CEO告诉你---编程。今年新加入摩根大通的全部资产管理分析师必须强制学习编程语言&#xff0c;Python。摩根大通资管经理Mary Callahan Erodes表示“现代资产管理的唯一语言是编程语言”。因为强制普及编程语言&#xff0c;现在…

java exec 关闭_如何正确关闭java ExecutorService

从ExecutorService的 Oracle API文档页面推荐的方法&#xff1a;void shutdownAndAwaitTermination(ExecutorService pool) {pool.shutdown(); // Disable new tasks from being submittedtry {// Wait a while for existing tasks to terminateif (!pool.awaitTermination(60,…

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

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

iterate mysql_ITERATE

OutOfOrderScannerNextException: was there a rpc tiaused by: java.util.concurrent.ExecutionException: org.apache.phoenix.exception.PhoenixIOException: Failed after retry of OutOfOrderScannerNextExcept...文章余二五2017-11-222749浏览量Hibernate-ORM:05.Hiberna…

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

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