JQuery ajax跨域请求(JSONP CORS)

AJAX一种创建交互式网页应用的技术,用于创建快速动态网页。
一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
在使用ajax的情况下,我们经常经常进行跨域请求
那么我们使用过程中,如何进行跨域请求呢?

方法一:Ajax发起JSONP跨域请求

我们通过jQuery的JSONP方式可以实现跨域ajax请求,服务端php也需要做出相应的处理,也就是说php这边必须和前端页面按照一定的格式请求和返回数据(json数组)。
注意:使用jsonp的时候,只有get 类型可用,即使设置了 post类型,还是使用的 get

$.ajax({
    type: "get", //规定请求的类型(GET 或 POST)。
    data: "random="+Math.random(),  //  规定要发送到服务器的数据。
    url: "https://fengkui.net/ceshi.php",  //规定发送请求的 URL。默认是当前页面。
    dataType: "jsonp",  //预期的服务器响应的数据类型。
    jsonp: "callback",  //在一个 jsonp 中重写回调函数的字符串。
    success: function(data) {  //请求成功后返回
        console.log(data);
    },
    error: function() {  //请求失败后返回
        console.log('Request Error.');
    }
});

我们发现,ajax跨域请求参数中有 dataType: "jsonp" 和 jsonp: "callback" ,这个就表明了我要请求的是jsonp,并且会有回调callback返回。当然,我们也可以自定义回调函数,如 jsonpCallback:"success_jsonpCallback"
还可以简单的写成:

jQuery.getJSON("https://fengkui.net/ceshi.php?callback=?",{
    random: Math.random()
}, function(data){
    console.log(data);
});

php后端服务代码可以这样写(注意输出返回的格式):

$data = array(
  'rand' => $_GET['random'],
  'msg' => 'Success'
);
echo $_GET['callback'].'('.json_encode($data).')';

方法二:Ajax跨域请求:CORS(点击查看详细介绍

CORS是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略,浏览器会禁止这种跨域请求。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

通常在浏览器发送AJAX跨域请求时,就自动在头信息之中,添加一个Origin字段,用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
在服务端框架入口文件中加入以下代码,即接受任意域名、任意类型的请求。

// 指定允许其他域名访问
header('Access-Control-Allow-Origin: *');
// 响应类型
header('Access-Control-Allow-Methods: *');
// 响应头设置
header('Access-Control-Allow-Headers: x-requested-with, content-type');

当然我们也可以按照如下设置,限定特定的域名、特定的类型允许请求,

// 指定允许特定域名访问
header('Access-Control-Allow-Origin: https://fengkui.net');
// 响应类型
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
// 响应头设置
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept');

多个域名建议使用以下写法:

// 指定允许其他域名访问
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
$allow_origin = array('https://fengkui.net','https://a.fengkui.net','https://b.fengkui.net');
if(in_array($origin, $allow_origin)){
    header('Access-Control-Allow-Origin:'.$origin);
}
// 响应类型
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
// 否允许发送Cookie
header('Access-Control-Allow-Credentials:true');
// 响应头设置
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Apikey");

(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求,多个域名用逗号分隔。

(2)Access-Control-Allow-Methods
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

(2)Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
在CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

设置完成服务的CORS之后我们就可以直接使用JSON进行请求,如下:

$.ajax({
    type: "POST",
    data: {'ceshi':'ceshi'},
    url: "https://fengkui.net/ceshi.php",
    dataType: "json",
    xhrFields: {withCredentials: true},  //一对“文件名-文件值”在本机设置XHR对象。例如,用它来设置withCredentials为true的跨域请求。 用户固定PHPSESSID不变
    success: function(data) {
        console.log(data);
    },
    error: function() {
        console.log('Request Error.');
    }
});

冯奎博客

总结:CORS与JSONP的使用目的相同,但是比JSONP更强大,JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

冯奎博客
请先登录后发表评论
  • latest comments
  • 总共0条评论