Ajax跨域(一)CORS跨域

本文总结自极客学院跨域Ajax实现视频教程地址
常用的Ajax跨域请求有:CORS(跨域资源共享)、JSONP跨域和iframe跨域通信

一、CORS原理:

xhr level2支持的新标准,XMLHttpRequest随想原生支持ajax,支持xhr level2的浏览器就能发起ajax跨域请求。但是它也有一定的安全限制,并不是支持了xhr level2的浏览器就能直接发起ajax跨域请求,只是说,它在标准上有实现跨域的功能,我们需要通过一定的安全策略,让这个功能真正的支持起来。

二、CORS实现

  • 实现CORS跨越请求关键在于,如何通过安全策略的设置,让跨域ajax的功能真正的发起。
  • 当浏览器判定一个请求为跨域请求时,它会在请求头信息中查找,是否存在一个“Access-Control-Allow-Origin”字段,并且该字段的值是允许一个域向另一个域发起请求的,这时请求就会被通过。
  • 当我们向一个域发起请求时,后端实际上已经将结果相应给了前台,但是前台是否能够使用后台返回的数据,并交给前端脚本处理,取决于响应信息中是否有一个允许使用的标志(Access-Control-Allow-Origin),它的值就是允许访问的域(如:a.test.com)。如果我们希望一个域(a.test.com)能够访问另一个域(b.test.com),那么另一个域(b.test.com)的响应信息中就必须包含允许访问的标志,它的值就是我们发起请求的域的名称(a.test.com)

三、CORS跨域资源共享分类

  • 简单请求:浏览器直接发出CORS请求,具体来说,就是在头信息中,增加一个Origin字段,用来说明本次请求来自哪个源(协议+域名+端口),服务器根据这个值,决定是否同意这次请求。
    1.根据服务器的返回头信息是否包含“Access-Control-Allow-Origin”字段,来判断请求是否出错(“Access-Control-Allow-Origin”字段是必须的,它的值要么是Origin字段的值,要么是一个星号“*”,表示接受任意域名的请求。)
    2.CORS请求默认不发送Cookie和Http认证信息,如果要把Coolie发送到服务器,一方面要服务器同意,另一方面,开发者要在Ajax请求中打开“withCreditials”属性:
var xhr = new XMLHttpRequest();
xhr.withCreditials = true;
  • 非简单请求:对服务器有特殊要求的请求,比如请求方式是 “PUT”或“DELETE”等。
    非简单请求的CORS请求会在正式通信前,增加一次HTTP查询请求,成为“预检”请求(Preflight)。预检请求用的请求方式是“OPTIONS”,表示该请求时用来询问的,关键字段是Origin。

三、CORS跨域演示

修改host文件来模拟跨域(C:\Windows\System32\drivers\etc)
在host文件中添加:

127.0.0.1   a.test.com
127.0.0.1   b.test.com

便可利用a.test.com和b.test.com来模仿两个域,实现跨域请求。
此处演示用node.js来作后台处理。

  • package.json文件
{
  "name": "ajax-cross-domain",
  "description": "cross ajaxs",
  "version": "0.0.1",
  "main": "./app.js",
  "dependencies": {
    "express": "4.x",
    "body-parser": "*"
  }
}
  • app.js
var express = require('express');
var path = require('path');
var bodyParer = require('body-parser');

var app = express();

app.use(bodyParer.json());
app.use(bodyParer.urlencoded({
    extended: false
}));

app.use(express.static(path.join(__dirname,'public')));

/*设置响应头信息,在这里做一个头信息通用设置,即在发起请求前设置,达到在一个位置设置,所有位置都能生效的效果*/
app.use(function(req,res,next) {
    res.header("Access-Control-Allow-Origin", "a.test.com");
    //设置响应头信息,若想让所有请求域都通过,可以将值设置为“*”
    res.header("Access-Control-Allow-Headers", "test");
    res.header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
    next();
});

app.use('/',require('./routes/index.js'));

var DEFAULT_PORT = 3000;
app.listen(DEFAULT_PORT);
console.log('server is listen at port: %d',DEFAULT_PORT);
  • index.js
/**
 * Created by lenovo on 2016/8/4.
 */
var express = require('express');
var router = express.Router();

router.all('/',function(req,res) {
    res.sendFile('./public/index.html');
});

router.all('/test',function(req,res) {
    res.send('ok');
});

module.exports = router;
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>cors</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="css/main.css">
    <script src="js/jquery-1.11.3.js"></script>
</head>
<body>
     <div class="container">
         <button class="btn btn-primary" onclick="crossAjax()">CORS</button>
     </div>

    <script>
        function crossAjax() {
            $.ajax('http://b.test.com:3000/test',{
                type: 'PUT',    //请求方式不是“get”时,需要在响应信息中设置“Access-Control-Allow-Methods”字段
                headers: {test: 'ok'}    //当设置了自定义头部时,需要在响应信息中设置“Access-Control-Allow-Headers”字段,否则请求被阻止。
            }).done(function(data) {
                alert(data);
            })
        }
    </script>
</body>
</html>

在浏览器中输入a.test.com的域名,即可向b.test.com发送请求(反过来一样可以。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章