ajax跨域

一、什么是跨域?

  • 一般来说,当一个请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。最常见的就是在一个域名下的网页中,调用另一个域名中的资源。
  • 当浏览器报这样的错的时候,就是跨域请求出问题了!
从根源上讲,跨域是由浏览器安全的同源策略引起的!

同源策略是由Netscape提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源(origin)中加载文本或者脚本与来自其他源(origin)中资源的交互方式。

  • 所谓的同源就是指的:协议、域名、端口相同。
  • 当浏览器执行一个脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域。
同源策略是出于安全考虑

对js进行限制,防止恶意用户获取非法数据,同时还防止了大部分XSS攻击(就是向用户界面注入js脚本)。

通常跨域是由以下两种同源策略造成的
  • DOM同源策略。禁止对不同源的页面的DOM进行操作,主要包括iframe、canvas之类的。不同源的iframe禁止数据交互的,含有不同源数据的canvas会受到污染而无法进行操作。
  • XmlHttpRequest同源策略。简单来说就禁止不同源的AJAX请求。

二、解决跨域的方法

1. jsonp

首先,我们需要认知:
1. jsonp是一种非正式协议。
2. scrpitsrc属性不受同源限制,有跨域请求的能力!(img也不受限制)
3. jsonp通过script的src属性引入一个js文件,并返回一个js函数的调用!
总的来说就是利用了script标签不受同源策略的限制去获取数据。这就是jsonp原理
具体操作流程为:
1. 动态创建script标签。
2. 绑定src路径到想访问的地址。
3. 添加到document.body.appendChild()中!
4. 通过函数声明,进行你想进行的数据操作。

一个简单的jsonp

function fun(data) {  //回调函数
    console.log(data);  //对数据的处理
};
var body = document.getElementsByTagName('body')[0];
var script = document.gerElement('script');
script.type = 'text/javasctipt';
script.src = 'http://example.com?jsonp=cb';
body.appendChild(script);

实例:

百度搜索框!

以下为搜索关键字wd=apple

https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=apple&cb=abc

js返回的结构:

abc({q:”apple”,p:false,s:[“apple中国官方网站”,”apple中国”,”apple store官网”,”apple id”,”apple pay”,”apple pay 5折”,”apple watch”,”apple developer”,”apple id注册”,”apple pay如何使用”]});

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="Author" content="FengYu">
        <title>Tz-36期Js</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                font-family: Microsoft YaHei, serif;
            }

            li {
                list-style: none;
            }

            #box {
                width: 400px;
                margin: 50px auto;
            }

            input {
                width: 398px;
                height: 35px;
                border: 1px solid #ddd;
            }

            ul {
                width: 398px;
                border: 1px solid #666;
                cursor: pointer;
            }

            ul li {
                line-height: 30px;
                text-indent: 10px;
            }

            ul li:hover {
                background: #888;
                color: #fff;
            }
        </style>
    </head>
    <body>
        <div id="box">
            <input type="text">
            <ul>

            </ul>
        </div>
        <script>
            var Ul = document.getElementsByTagName("ul")[0],
                input = document.getElementsByTagName("input")[0];
            //https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+val+"&cb=abc  百度的js搜索文件
            input.oninput = function() {
                var val = this.value;
                var script = document.createElement("script");
                script.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + val + "&cb=abc";
                document.body.appendChild(script);
                script.onload = function() {
                    document.body.removeChild(this)
                }
            }

            function abc(obj) {
                var arr = obj.s;
                Ul.innerHTML = "";
                for(var i in arr) {
                    Ul.innerHTML += '<li>' + arr[i] + '</li>'
                }
            }

            //事件代理
            Ul.onclick = function(e) {
                var This = e.target; //事件源
                if(/li/i.test(This.nodeName)) {
                    window.open("https://www.baidu.com/s?wd=" + This.innerHTML)
                }
            }
        </script>
    </body>
</html>

总结:

这种方法所有浏览器都兼容,前端可以很轻松的做到跨域请求,但也有一些缺点:

  • 只能通过GET方式请求,一方面是参数长度有限制,二是安全性比较差;
  • 只能通过js传回数据!
  • 后端需要知道前端的abc是什么样的结构,主要在参数回调函数名,并进行相应配置;
  • 它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

2. CORS(跨域资源共享)

概念:
Cross-Origin Resource Sharing(跨域资源共享)是一个W3C标准,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

在分析CORS之前,还需要了解一下ajax跨域报错产生的过程。
  • 使用XMLHttpRequest发送数据请求时,浏览器如果发现违反了同源策略(跨域请求资源时)就会自动在请求头(Request Header)中加上一个字段:origin。此字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。
  • 服务器CORS端会根据这个源的值,判断是否在许可范围,若不符合返回的HTTP响应头(Response Header)信息则会缺少Access-Control-Allow-Origin项,从而抛出一个错误。如同文章开头我们看到的那样!

也就是说,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,将目标源纳入许可范围,就可以跨源通信。
origin的url值在许可范围内,服务器会返回包含以下头信息字段。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar

随后,浏览器检测到

Access-Control-Allow-Origin 项

就可以允许Ajax进行跨域的访问。
简单CORS跨域例子:
平时的ajax请求可能是这样的:

<script type="text/javascript">
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/damonare",true);
    xhr.send();
</script>

以上damonare部分是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:

<script type="text/javascript">
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);
    xhr.send();
</script>

总结:

  • 现代浏览器中和移动端都支持CORS(除了opera mini),IE下最好10+
  • CORS支持所有类型的HTTP请求。
  • CORS更为先进和方便,但需要服务器端进行处理。

3.通过HTML5的postMessage

window.postMessage属于html5的新特性

  • 这个功能主要包括接受信息的”message”事件和发送消息的”postMessage”方法。比如damonare.cn域的A页面通过iframe嵌入了一个google.com域的B页面,可以通过以下方法实现A和B的通信!

A页面通过postMessage方法发送消息:

window.onload = function() {  
    var ifr = document.getElementById('ifr');  
    var targetOrigin = "http://www.google.com";  
    ifr.contentWindow.postMessage('hello world!', targetOrigin);  
};

postMessage的使用方法:

  • otherWindow.postMessage(message, targetOrigin);
    - otherWindow:指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口
    - message: 是要发送的消息,类型为 String、Object (IE8、9 不支持)
    - targetOrigin: 是限定消息接收范围,不限制请使用 *

B页面通过message事件监听并接受消息:

var onmessage = function (event) {  
  var data = event.data;//消息  
  var origin = event.origin;//消息来源地址  
  var source = event.source;//源Window对象  
  if(origin=="http://www.baidu.com"){  
console.log(data);//hello world!  
  }  
};  
if (typeof window.addEventListener != 'undefined') {  
  window.addEventListener('message', onmessage, false);  
} else if (typeof window.attachEvent != 'undefined') {  
  //for ie  
  window.attachEvent('onmessage', onmessage);  
}

同理,也可以B页面发送消息,然后A页面监听并接受消息。
总结:

  • postMessage非常适合进行页面间跨域通信
  • 需要较高版本的浏览器,IE10+.

4. 服务器代理

可以在服务器端设置一个代理,由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制。
最简单操作,给url加一个前缀即可!

'https://bird.ioliu.cn/v1?url='+url(请求资源的地址)

5.通过window.name跨域

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

window.name = "My window's name";
setTimeout(function(){
    window.location.href = "http://damonare.cn/";
},1000)

进入damonare.cn页面后我们再检测再检测 window.name :

window.name; // My window's name

可以看到,如果在一个标签里面跳转网页的话,我们的 window.name 是不会改变的。

例子:
在 iframe.html 中设置好了 window.name 为我们要传递的字符串。
我们在 index.html 中写了下面的代码,可实现跨页面传数据:

var iframe = document.getElementById('iframe');
var data = '';

iframe.onload = function() {
    iframe.onload = function(){
        data = iframe.contentWindow.name;
    }
    iframe.src = 'about:blank';
};

总结
- 此方法适合进行页面间跨域通信!

最后,还有一种偏门的方法,简单粗暴!

这里写图片描述
关闭浏览器安全机制,仅在测试代码时使用。

解除浏览器安全审核,可以免去跨域操作,直接进行请求!

   chrome.exe -disable-web-security -user-data-dir

参考文章:
跨域资源共享
跨域那些事
跨域

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值