一、跨域问题
跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。
注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
二、解决办法
1.使用JSONP(只支持GET请求,不支持POST请求)
对于JSONP不了解的,可以参看这篇文章:点击打开链接
客户端在使用Ajax访问是将dataType的值设为JSONP
服务器端
2.服务器代理
例如www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.php,由这个接口在后端去调用www.456.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题。
3.使用CORS
服务器端设置请求头的拦截,以解决跨域问题
res.header("Access-Control-Allow-Origin", '*'); // 允许所有来源访问
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); // 允许访问的方式
res.header("Access-Control-Allow-Credentials", true); //可以带cookies
res.header("Content-Type", "application/json;charset=utf-8");
4. postMessage
window.postMessage(message,targetOrigin) 方法是 HTML5 新引进的特性,可以向其它的 window 对象发送消息,无论这个 window 对象是属于同源或不同源。调用 postMessage 方法的 window 对象是指要接收消息的那一个 window 对象,该方法的第一个参数 message 为要发送的消息,类型只能为字符串;第二个参数 targetOrigin 用来限定接收消息的那个 window 对象所在的域,如果不想限定域,可以使用通配符 *。需要接收消息的 window 对象,可是通过监听自身的 message 事件来获取传过来的消息,消息内容储存在该事件对象的 data 属性中。
// 页面 http://www.test.cn/a.html 的代码:
<iframe src="http://test.cn/b.html" id="myIframe" onload="test()" style="display: none;">
<script>
// 1. iframe载入 "http://test.cn/b.html 页面后会执行该函数
function test() {
// 2. 获取 http://test.cn/b.html 页面的 window 对象,
// 然后通过 postMessage 向 http://test.cn/b.html 页面发送消息
var iframe = document.getElementById('myIframe');
var win = iframe.contentWindow;
win.postMessage('我是来自 http://www.test.cn/a.html 页面的消息', '*');
}
</script>
// 页面 http://test.cn/b.html 的代码:
<script type="text/javascript">
// 注册 message 事件用来接收消息
window.onmessage = function(e) {
e = e || event; // 获取事件对象
console.log(e.data); // 通过 data 属性得到发送来的消息
}
</script>
5. document.domain
同源策略认为域和子域属于不同的域,如:child1.a.com 与 a.com,可以通过设置 document.damain='a.com',浏览器就会认为它们都是同一个源。想要实现以上任意两个页面之间的通信,两个页面必须都设置documen.damain='a.com'。特点如下:
(1) 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,不能再设置成child1.a.com。
(2) 存在安全性问题,当一个站点被攻击后,另一个站点会引起安全漏洞。
(3) 只适用于 Cookie 和 iframe 窗口。
6. window.name
window 对象的 name 属性,在一个窗口(window)的生命周期内,窗口载入的所有的页面(不管是相同域的页面还是不同域的页面)都是共享一个 window.name
的,每个页面对 window.name
都有读写的权限,window.name
是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
// 页面 http://www.test.cn/a.html 的代码:
<iframe src="http://test.cn/b.html" id="myIframe" onload="test()" style="display: none;">
<script>
// 2. iframe载入 "http://test.cn/b.html 页面后会执行该函数
function test() {
var iframe = document.getElementById('myIframe');
// 重置iframe的onload事件程序,此时经过后面代码重置src之后,http://www.test.cn/a.html页面与该iframe在同一个源了,可以相互访问了
iframe.onload = function() {
var data = iframe.contentWindow.name; // 4. 获取 iframe 里的 window.name
console.log(data); // hello world!
};
// 3. 重置一个与 http://www.test.cn/a.html 页面同源的页面
iframe.src = 'http://www.test.cn/c.html';
}
</script>
// 页面 http://test.cn/b.html 的代码:
<script type="text/javascript">
// 1. 给当前的 window.name 设置一个 http://www.test.cn/a.html 页面想要得到的数据值
window.name = "hello world!";
</script>
7.location.hash
该方式跨域是因为子框架可以修改父框架 src 的 hash 值,通过这个属性进行传递数据,且更改 hash 值,页面不会刷新。但是传递的数据的字节数是有限的。
// 页面 http://www.test.cn/a.html 的代码:
<iframe src="http://test.cn/b.html" id="myIframe" onload="test()" style="display: none;">
<script>
// 2. iframe载入 "http://test.cn/b.html 页面后会执行该函数
function test() {
// 3. 获取通过 http://test.cn/b.html 页面设置 hash 值
var data = window.location.hash;
console.log(data);
}
</script>
// 页面 http://test.cn/b.html 的代码:
<script type="text/javascript">
// 1. 设置父页面的 hash 值
parent.location.hash = "world";
</script>
【注意】参考博客:https://www.cnblogs.com/itmacy/p/6958181.html
https://blog.csdn.net/u014727260/article/details/72793459