JavaScript基础概念之----跨域

浏览器对于javascript的同源策略的限制,出现了跨域。

只要协议、域名、端口等不同,就会出现跨域:如下

域名:
 主域名不同 http://www.a.com –>http://www.b.com
 子域名不同 http://www.m.a.com/index.html –>http://www.n.a.com/test.js
 域名和域名ip http://www.a.com/index.html –>http://188.44.77.98/test.js
端口:
 http://www.a.com:8080/index.html–> http://www.a.com:9090/test.js
协议:
 http://www.a.com:8080/index.html–> https://www.a.com:8080/test.js
其他:
 1、端口和协议的不同,只能通过后台来解决
 2、localhost和127.0.0.1虽然都指向本机,但也属于跨域

解决跨域有下面几种方法:

  • jsonp跨域(JSON with Padding 填充式JSON)
  • document.domain
  • wndow.name
  • postMessage
  • 后端修改header
  • nginx反向代理

JSONP跨域

只支持get请求。返回的是脚本代码(包含一个函数调用)。

通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

<script>
function dosomething(jsonData){
    //处理获得的json数据
}
</script>
<script src="http://xxx.com/test.jsp?callback=dosomething"></script>

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

<script>
$.getJSON('http://xxx.com/data.jsp?callback=?',function(jsonData){
    //处理获得的JSON数据
})
</script>

document.domain

浏览器中不同域的框架之间是不能进行js的交互操作的。

比如,有一个页面,它的地址是http://www.example.com/a.html  , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

<script>
function onload(){
    var iframe = document.getElementById('iframe')
    
    //这里能获取到iframe里的window,但该window的属性和方法是不可用的
    var win = iframe.contentWindow
    //这里获取不到iframe里的document
    var doc = win.document
    //这里获取不到window的name
    var name = win.name
</script>
<iframe id="iframe" src="http://example.com/b.html" οnlοad="onload()"></iframe>

我们只要把http://www.example.com/a.htmlhttp://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。

在页面 http://www.example.com/a.html 中设置document.domain:

<iframe id="iframe" src="http://example.com/b.html" οnlοad="test()"></iframe>
<script>
document.domain = 'example.com'; // 设置成主域
function test(){
    alert(document.getElementById('iframe').contentWindow)
</script>

在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

<script>
document.domain = 'example.com'; // 也设置成主域
</script>

window.name

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

window.name的值只能是字符串的形式。

比如有一个www.example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.cnblogs.com/data.html里的数据。

data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

<script>
window.name = '我是页面a.html需要的数据'
</script>

在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。把这个iframe的src设为www.cnblogs.com/data.html就行了。还必须把这个iframe的src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是整个跨域过程。

<script>
function getData(){
    var iframe = document.getElementById('proxy')
    iframe.onload = function(){
        var data = iframe.contentWindow.name;
        alert(data)
    }
    iframe.src = 'b.html'
}
</script>

<iframe id="proxy" src="http://www.cnblogs.com/data.html" style="display:none;" οnlοad="getData()"></iframe>

window.postMessage

是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 *  。

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

//这是 页面 http://test.com/a.html 中的代码

<script>
function onLoad(){
    var iframe = document.getElementById('iframe')
    var win = iframe.contentWindow;//获取window对象
    win.postMessage('我是来自a.html的消息')//向不同域页面发送消息
}
</script>
<iframe id="iframe" src="http://www.test.com/b.html" οnlοad="onLoad()"></iframe>
//这是 页面http://www.test.com/b.html的代码

<script>
window.onmessage = function(e){ //注册message事件来接收消息
    e = e || event;//获取事件对象
    alert(e.data)//通过data属性得到传送的消息
}
</script>

后端修改header

header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问

header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

 

nginx反向代理

Nginx配置

server{
    # 监听9099端口
    listen 9099;
    # 域名是localhost
    server_name localhost;
    #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
    location ^~ /api {
        proxy_pass http://localhost:9871;
    }    
}

网上更详细的资源:https://segmentfault.com/a/1190000015597029

 

转载于:https://www.cnblogs.com/adhehe/p/9792187.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值