跨域请求解决方案

浏览器安全的基石是“同源政策”

1.同源政策含义

A 网页设置的 Cookie,B 网页不能打开,除非这两个网页“同源”。
不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。
所谓“同源”指的是”三个相同
协议相同
域名相同
端口相同

举例来说,http://www.example.com:80/dir/page.html这个网址,
协议是http://,
域名是www.example.com
端口是80(默认端口可以省略)。

2.跨域

跨域解决方案
1、 通过jsonp跨域 !
2、 document.domain + iframe跨域 !
3、 location.hash + iframe !
4、 window.name + iframe跨域 ?
5、 postMessage跨域 ?
6、 跨域资源共享(CORS) ?
7、 nginx代理跨域 ?
8、 nodejs中间件代理跨域 ?
9、 WebSocket协议跨域 ?

2.1 JSONP跨域

一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
它的基本思想是,网页通过添加一个script元素,向服务器请求 JSON 数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
步骤:
脚本动态插入


function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};

上面代码通过动态添加script元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于 JSONP 是必需的。
服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。


foo({
  "ip": "8.8.8.8"
});

由于script元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的 JSON 数据被视为 JavaScript 对象,而不是字符串,因此避免了使用JSON.parse的步骤。
凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<\script>、<\img>、<\iframe>

推荐一篇文章

https://blog.csdn.net/hansexploration/article/details/80314948

2.2document.domain跨域

此方法有个前提:只有主域名相同的情况下方可使用此方法

介绍document.domain跨域之前我们先补充几个知识点

URL的组成

http://mail.163.com/index.html
http://:这个是协议,也就是HTTP超文本传输协议,也就是网页在网上传输的协议。
mail:这个是服务器名,代表着是一个邮箱服务器,所以是mail.
163.com:这个是域名,是用来定位网站的独一无二的名字。
mail.163.com:这个是网站名,由服务器名+域名组成。
/:这个是根目录,也就是说,通过网站名找到服务器,然后在服务器存放网页的根目录
index.html:这个是根目录下的默认网页(当然,163的默认网页是不是这个我不知道,只是大部分的默认网页,都是index.html)

http://mail.163.com/index.html:这个叫做URL,统一资源定位符,全球性地址,用于定位网上的资源。
163.com他的域名是163.com,他想建立一个www服务器,所以有了www.163.com.
他又想玩邮箱服务器,所以,mail.163.com也有了。
一级域名(根域名),如:sojson.combaidu.comsina.comsina.com.cnsina.cn.net 等等。
二级域名 是指增加了一级,包括www。如:www.sojson.comicp.sojson.comzhidao.baidu.comwww.baidu.com 等等。有人把www.sojson.com叫一级域名这是错误的。

什么是主域名相同

huhu.com
a.huhu.com
b.a.huhu.com
这是三个不同的域名,但是主域名是相同的 都是 huhu.com, 不是这种形式的那么都不能用document.domain方法跨域。

console.lg(document.domain)

用来得到当前网页的域名。
在这里插入图片描述

利用document.domain 实现跨域:

前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域.
Javascript出于对安全性的考虑,而禁止两个或者多个不同域的页面进行互相操作。
相同域的页面在相互操作的时候不会有任何问题。

实现原理:通过js强制设置两个页面的基础主域为document.domain,就实现了同域。
1.)父窗口:(http://www.domain.com/a.html)


<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin';
</script>

2.)子窗口:(http://child.domain.com/b.html)


<script>
    document.domain = 'domain.com';
    // 获取父窗口中变量
    alert('get js data from parent ---> ' + window.parent.user);
</script>

window.parent 属性返回当前窗口的父窗口。

https://www.cnblogs.com/zichi/p/4620656.html

2.3 location.hash + iframe跨域

location对象的hash属性

location对象是javascript管理地址栏的内置对象。
location.href 就管理页面的url,用 location.href=url 就可以直接将页面重定向 url。location.hash 则可以用来获取或设置页面的标签值。比如 http://domain/#admin 的location.hash="#admin"
#代表网页中的一个位置。其右面的字符,就是该位置的标识符。比如,
  http://www.example.com/index.html#print
就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。
为网页位置指定标识符,有两个方法。
一是使用锚点,比如<a name="print"></a>
二是使用id属性,比如<div id="print" >

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端
比如,下面URL的原意是指定一个颜色值:
  http://www.example.com/?color=#fff
但是,浏览器实际发出的请求是:
  GET /?color= HTTP/1.1
  Host: www.example.com

实现原理a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

(我看明白了 日后再回来总结…)

https://www.cnblogs.com/zichi/p/4621963.html
http://rolfzhang.com/articles/380.html
http://www.cnblogs.com/skylar/p/4101443.html#comments

2.2WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。

2.3cors

浏览器发出的请求的头信息有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应。

2.4postMessage

HTML5提供的新API – postMessage
postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
用法:postMessage(data,origin)方法接受两个参数
1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。
2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

https://segmentfault.com/a/1190000011145364

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值