Ajax跨域请求

一 . Ajax跨域请求简介

在前端的开发中,有时候需要跨域发起Ajax请求,本文将讲述跨域发起Ajax请求的几种方式。

二 . Ajax跨域请求方案之iframe

a.test.com 与b.test.com 之间进行通信的话,可以用iframe进行。
iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。
iframe可以在子域之间进行通信,比如上面两个就可以看做test.com的两个子域。
http://b.test.com/cross_sub_domain.html 利用这个页面做中间人,这个页面是b的域的页面,所以可以
与b域进行ajax通信,然后a域和这个中间人通过iframe进行通信,得到从b域得到的数据。
a.test.com 中
<iframe id="bfrm" style="display:none;" src="http://b.test.com/cross_sub_domain.html">iframe>
<button class="btn-sm btn btn-primary" onclick="crossSubDomain();">跨子域请求button>
<script>
function crossSubDomain() {
        document.domain = 'test.com'; // 提升域 关键操作
        window.frames['bfrm'].contentWindow.doAjax(function(data) {
            alert(data);
        });
    }
script> 

http://b.test.com/cross_sub_domain.html 中
<script>
        document.domain = 'test.com';  //提升域 关键操作
        function doAjax(callback) {
            $.ajax('/test').done(function(data) {
                callback(data);//a域的回调函数可以得到b域的数据。
            });
        }
script>
问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

三 . Ajax跨域请求方案之JSONP

jsonp原理:
本质上并不是ajax,只是执行了跨域的js。
html中所有带src属性的标签都可以跨域script img iframe
所以,可以通过script加载其他域的一段动态脚本,这段脚本包含了想要的数据信息。
jsonp.html



要返回数据的index.js中
var express = require('express');
var router = express.Router();
router.all('/testjsonp', function(req, res) {   //利用express响应testjsonp路由,然后返回一个回调函数,并将要传输的数据写入回调函数的参数。
    res.setHeader('Content-Type', 'application/javascript'); //callback({a:1,b:2});
    res.send('callback(' + JSON.stringify({a:1, b:2}) + ')');
});
动态生成JavaScript标签的做法:


function jsonp(url, data, callback) {
    var script = document.createElement('script');
    document.body.appendChild(script);

    data = data || {};
    data.callback = 'cb' + new Date().getTime();
    window[data.callback] = callback;

    url += '?' + $.param(data);

    script.src = url;
    script.onload = function () {
        document.body.removeChild(script);
    }
}

function calltest() {
    jsonp('http://b.test.com/testjsonp2', {test: 'ok'}, function (data) {
        console.log(data);
    });
}
router.all('/testjsonp2', function(req, res) {
    res.setHeader('Content-Type', 'application/javascript'); //cb123({a:1,b:2})
    res.send(req.query.callback + '(' + JSON.stringify({a:1, b:2}) + ')');
});
以上过程我们可以用jquery来实现,使用jquery 的getJSON方法 发起jsonp。
getJSON 方法的参数如下:
getJSON(url, data, callback);

function testGetJson() {
    $.getJSON('http://b.test.com/testjsonp2?callback=?', {test: 'ok'}, function(data) {  //url中必须有 函数名称(如 ?callback=?名称任意)否则就不会被认为是跨域的请求
       console.log(data);
    });
}
还可以用jquery的ajax方法发起

jsonp jsonpCallback 参数

function testArgs() { $.ajax('http://b.test.com/testjsonp3', { dataType: 'jsonp', jsonp: 'cbname', jsonpCallback: 'cbfun', cache: true, success: function(data) { console.log(data); } }); } router.all('/testjsonp3', function(req, res) { res.setHeader('Content-Type', 'application/javascript'); res.send(req.query.cbname + '(' + JSON.stringify({a:1, b:2}) + ')'); }); jsonp的缺点: 只支持get方式 后端代码需要调整

四 . Ajax跨域请求方案之CORS

CORS原理:
xhr level2 支持的新标准,允许发起ajax请求。
但是为了跨域安全,需要在服务器响应头部提供一些信息,供浏览器校验请求是否被允许。
以下是需要提供的响应头部信息:
<p><b>Access-Control-Allow-Originb>p>
<p><b>Access-Control-Allow-Methodsb>p>
<p><b>Access-Control-Allow-Headersb>p>

<button class="btn btn-primary btn-sm" onclick="crossAjax();">CORS TESTbutton>
<script>
function crossAjax() {
    $.ajax('http://b.test.com/test', {
        type: 'PUT',
        headers: {test: 'haha'}
    }).done(function(data) {
        alert(data);
    });
}
script>

后端
router.all('/test', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', 'http://a.test.com');
    ////res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'test,other');

    res.send('ok');
});
CORS头信息通用设置方法:
http://enable-cors.org/server.html

你可能感兴趣的:(ajax,前端,Ajax)