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

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

只要协议、域名、端口等不一样,就会出现跨域:以下html

域名:
 主域名不一样 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
其余:
 一、端口和协议的不一样,只能经过后台来解决
 二、localhost和127.0.0.1虽然都指向本机,但也属于跨域html5

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

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

JSONP跨域jquery

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

经过script标签引入一个js文件,这个js文件载入成功后会执行咱们在url参数中指定的函数,而且会把咱们须要的json数据做为参数传入。因此jsonp是须要服务器端的页面进行相应的配合的。json

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

知道jsonp跨域的原理后咱们就能够用js动态生成script标签来进行跨域操做了,而不用特地的手动的书写那些script标签。若是你的页面使用jquery,那么经过它封装的方法就能很方便的来进行jsonp操做了。segmentfault

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

document.domain后端

浏览器中不一样域的框架之间是不能进行js的交互操做的。api

好比,有一个页面,它的地址是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" onload="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" onload="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;" onload="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" onload="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

相关文章
相关标签/搜索