JavaScript 跨域

问题是怎样造成的? 问题的由来 相信很多人都或多或少了解过问题,尤其在现如今前后端分离大行其道的时候。 你在本地开发一个前端项目,这个项目是通过 node 运行的,端口是9528,而服务端是通过 spring boot 提供的,端口号是7001。 当你调用一个服务端接口时,很可能得到类似下面这样的一个错误: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gi6zOBkM-1589015502774)(https://upload-images.jianshu.io/upload_imag 阅读详情

JavaScript 跨域

原文链接:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

本文来自网络(http://f2e.me/200904/cross-scripting/,该网址已不能访问),仅作个人读书笔记之用,并稍作修改和补充。

什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL说明是否允许通信

http://www.a.com/a.js

http://www.a.com/b.js

同一域名下允许
http://www.a.com/lab/a.js

http://www.a.com/script/b.js

同一域名下不同文件夹允许
http://www.a.com:8000/a.js

http://www.a.com/b.js

同一域名,不同端口不允许
http://www.a.com/a.js

https://www.a.com/b.js

同一域名,不同协议不允许
http://www.a.com/a.js

http://70.32.92.74/b.js

域名和域名对应ip不允许
http://www.a.com/a.js

http://script.a.com/b.js

主域相同,子域不同不允许
http://www.a.com/a.js

http://a.com/b.js

同一域名,不同二级域名(同上)不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js

http://www.a.com/b.js

不同域名不允许

特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls

1、document.domain+iframe的设置

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。 具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上 document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以 “交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com 那显然是会报错地!代码如下:

www.a.com上的a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

2、动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility

这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。

js.onload = js.onreadystatechange = function() {
    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        // callback在此处执行
        js.onload = js.onreadystatechange = null;
    }
};

3、利用iframe和location.hash

这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可 以利用hash值来进行数据传递,当然数据容量是有限的。假设域名a.com下的文件cs1.html要和cnblogs.com域名下的 cs2.html传递信息,cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的 cs2.html页面,这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;Firefox可以修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一点有变化则获取获取hash值。代码如下:

先是a.com下的文件cs1.html文件:

function startRequest(){
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
    document.body.appendChild(ifr);
}

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : '';
        if (console.log) {
            console.log('Now the data is '+data);
        }
    } catch(e) {};
}
setInterval(checkHash, 2000);

cnblogs.com域名下的cs2.html:

//模拟一个简单的参数处理操作
switch(location.hash){
    case '#paramdo':
        callBack();
        break;
    case '#paramset':
        //do something……
        break;
}

function callBack(){
    try {
        parent.location.hash = 'somedata';
    } catch (e) {
        // ie、chrome的安全机制无法修改parent.location.hash,
        // 所以要利用一个中间的cnblogs域下的代理iframe
        var ifrproxy = document.createElement('iframe');
        ifrproxy.style.display = 'none';
        ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 注意该文件在"a.com"域下
        document.body.appendChild(ifrproxy);
    }
}

a.com下的域名cs3.html

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……

4、window.name实现的跨域数据传输

文章较长列在此处不便于阅读,详细请看 window.name实现的跨域数据传输

5、使用HTML5 postMessage

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。 下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。

otherWindow.postMessage(message, targetOrigin);
otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性; window.open的返回值;通过name或下标从 window.frames取到的值。
message: 所要发送的数据,string类型。
targetOrigin: 用于限制otherWindow,“*”表示不作限制

a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                        // 若写成'http://c.com'就不会执行postMessage了
    ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

b.com/index.html中的代码:

<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"I was there!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);
</script>

参考文章:《精通HTML5编程》第五章——跨文档消息机制https://developer.mozilla.org/en/dom/window.postmessage

6、利用flash

这是从YUI3的IO组件中看到的办法,具体可见http://developer.yahoo.com/yui/3/io/
可以看在Adobe Developer Connection看到更多的跨域代理文件规范:ross-Domain Policy File SpecificationsHTTP Headers Blacklist


postMessage实现JsJavascript通信 一、概要介绍 1、什么是是指从一个名的网页去请求另一个名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。但是一般情况下不能这么做,它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。的严格的定义是:只要 协议,名,端口有任何一个的不同,就被当作是。2、通信的解决方法: (1)通过jsonp实现... 阅读详情

相关推荐

专访高性能计算专家赵开勇:无人机/机器人开发实战,如何优化深度学习?

从能够自主飞行的无人机,到能和小朋友玩物体识别等游戏的机器人,极客们对智能设备追求没有止境。除了轻巧的体积、超长的续航,更重要的是要有一个智能的“大脑”,来实现人类能够想得到的人机交互,或者智能化的自主决策和行为动作,毫无疑问强大的深度学习能力不可或缺。那么,拒绝束缚人类想象力的嵌入式智能设备,其开发工作需要什么样的环境和工具?开发者进行相关开发的可行思路是什么?近日,CSDN记者就此专访了智能设...

happytofly的博客 3477

JavaScript总结与解决办法

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34223655的博客 198

RK3588开发板DDR频率上不去?手把手教你用ddrbin_tool降频调优(附完整配置流程)

本文详细介绍了RK3588开发板DDR频率调优的完整解决方案,重点使用ddrbin_tool工具进行降频配置。从硬件原理分析到实战操作,包括参数导出、频率调整、二进制生成及烧录验证,帮助开发者解决DDR高频不稳定问题,提升系统可靠性。适用于嵌入式开发、工业控制等场景。

weixin_42713608的博客 503

那些事儿

什么是 我们先看下以下场景:开启两个本地服务器,页面A为localhost:9800,其中嵌套了iframeB localhost:9000,页面A想使用页面B的数据,例如调用它的方法,会报以下错误 如图所示,Protocols,domains,and ports must match. 译为:协议、主机和端口号必须符合,否则,就是...

weixin_34362875的博客 356

的那些事儿

的那些事儿1. 什么是1. 同源策略常见的场景2.解决方案1. 通过jsonp2. 资源共享(CORS)3.nginx代理4.Nodejs中间件代理5. WebSocket协议6. 通过HTML5的postMessage方法7. 通过location.hash8. 通过document.domain 1. 什么是 一词从字面意思看,就是...

weixin_43678786的博客 1254

html5 postMessage解决iframe协议通信问题

a.html有个iframe载入b.com/login.html,当login完成时通知a.html页面登录完成并传递UserName 1.a.html 监听消息 window.addEventListener('message', function (event) { // 通过origin属性判断消息来源地址 //if (event.origin == 'http://127.0.0.1:10847') { console.log(eve

u011927449的博客 535

JavaScript中的问题

前言:学习JavaScript的童鞋都知道,我们在发送网络请求,也就是我们在地址栏输入一个网址,就会自动跳转到当前网址,比如在浏览器网址输入www.baidu.com,浏览器就会自动跳转到百度的的首页 而浏览器发送网络请求需要三和基本的要素 其实完成的url路径应该是:http://www.baidu.com:80浏览器在发送网络请求的时候回默认加上协议:http 和端口号80. 也就是完整的url至少 包含三个部分 1.http/https 传输协议 2.www.baidu.com 名 3.80.

weixin_43314255的博客 8120

js向php传数据,js请求数据的3种常用的方法_javascript技巧

由于js同源策略的影响,当在某一名下请求其他名,或者同一名,不同端口下的url时,就会变成不被允许的请求。那这个时候通常怎么解决呢,对此菜鸟光头我稍作了整理:1.JavaScript在原生js(没有jQuery和ajax支持)的情况下,通常客户端代码是这样的(我假设是在localhost:8080的端口下的http://localhost:8080/webs/i.mediapower.m...

weixin_34275113的博客 486

JavaScript html加载本地js文件出现问题

JavaScript html加载本地js文件出现问题 const modelUrl = './model.json' async function fun(){ const model = await tf.loadGraphModel(modelUrl); const zeros = tf.zeros([1, 224, 224, 3]); model.predict(zeros).print(); } fun() 加载本地model.json时出现问题 解决方案: 1 浏览器

weixin_43815222的博客 3085

JavaScript(三十六)js方法

一、概述 JS是指通过js在不同的之间进行数据传输或通信,如Ajax向一个不同的请求数据,或者通过JS获取页面中不同的框架中(iframe)的数据。只要协议、名、端口有任何一个不同,即为不同的; 网址是 http://baidu.com:8080?user=name&amp;pwd=password http: 协议 baidu.com 名 (注意...

We_jia的博客 323

JavaScriptJS引用本地文件CORS问题

场景 Three.js搭建3D场景时,模型贴图加载失败,报错: THREE.TextureLoader() Origin null is not allowed by Access-Control-Allow-Origin     分析 很显然,此时在浏览器上方可以看到file:///——标准的File协议(本地文件传输协议) File协议静态请求本地资源出现,这个请求被禁止。即File协议无法实现。   通俗的说(⭐️): file协议只能在本地访问,且这个访问只是

丧心病狂Loli控的博客 5086

jquery _springboot解决js前端问题,javascript问题解决

最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的问题,也是找了好久才找到解决方法。下面来讲解下解决步骤。一,编写Filter过滤器把下面代码放到你的springboot项目中就可以了package com.qcl; import org.springframework.stereotype.Component; import java.io....

weixin_39935388的博客 234

springboot解决js前端问题,javascript问题解决

最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的问题,也是找了好久才找到解决方法。下面来讲解下解决步骤。 一,编写Filter过滤器 把下面代码放到你的springboot项目中就可以了 package com.qcl; import org.springframework.stereotype.Component; import jav...

weixin_34162695的博客 383

java控制页面js_「JavaScriptJS四种方式详解

超详细并且带 Demo 的 JavaScript 指南来了!本文基于你了解 JavaScript 的同源策略,并且了解使用的理由。1. JSONP首先要介绍的方法必然是 JSONP。现在你想要获取其他网站上的 JavaScript 脚本,你非常高兴的使用 XMLHttpRequest 对象来获取。但是浏览器一点儿也不配合你,无情的弹出了下面的错误信息:XMLHttpRequest ...

weixin_33603802的博客 171

js问题_请求数据_jQuery

前两天跟一个朋友谈到的问题,对于,搞清原理,其实感觉应该是一个很简单的东西,理理思路,往下阅读这篇文章吧....js之概念:所谓,那么到底什么是呢?打个比方,用js加载本名的数据是没有问题的,那么我想加载另外一个名下的东西行不行呢?答案是不行的,为什么呢?因为javacript::同源策略的限制,yangyf.com名下的js是无法请求yangyanfei.com或是a.

兄弟连_战地日记 674

前端解决问题的8种方案

特别注意两点:第一,如果是协议和端口造成的问题“前台”是无能为力的,第二:在问题上,仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个或两个是否在同一个ip上。“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match...

ChenSutao的博客 352

type=“module“模式下的问题

html中使用type="module"的模式引入Js文件会报问题 <script type="text/javascript" src="a.js"></script> <script type="text/javascript" src="b.js"></script> <script type="module"> import './c.js' </script> a.js和b.js引入均正常 c.js

baidu_41604826的博客 6539

问题的解决方式

出现问题的时候通常会有如下报错: 这时候需要解决问题。 解决问题的步骤: 一、项目开始时webpack配置 项目刚开始,我们需要修改webpack配置,需要自己在项目根路径下创建vue.config.js文件。 二、在vue.config.js文件里面配置 proxy 请求 代码如下(示例): module.exports = { devServer: { //开发环境的服务器配置 open: false, // 是否会自动弹出浏览器 host: '0.0....

m0_64969829的博客 701

Vue使用type = “module“出现问题

代码为: <script src="aaa.js" type="module"></script> 出现的问题: 问题分析: 我们是用file协议来传输aaa.js这个文件的,可是CORS规定要用http,data,https等方式传输,所以就报错了。这是因为使用了type="module"的脚本Sec-Fetch-Mode是cors,常规引入的脚本Sec-Fetch-Mode是no-cors,不受同源策略的影响。 解决方案:安装live-serve插件,在本地创建一个服务器运行

韩旭不会敲代码吧的博客 2085

Huawei Fat&CloudAP7060DN-V200R019C00SPC926

Huawei Fat&CloudAP7060DN_V200R019C00SPC926,里面包含版本说明书和升级指导书,该版本支持哪些型号,支持哪些版本可以直接升级到当前版本,请参考版本说明书和升级指导书。

上一篇: [JavaScript语言精粹]学习笔记
下一篇: mysql中int、bigint、smallint 和 tinyint的区别与长度的含义
spring21st
博客等级 码龄20年 449粉丝 407原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值