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發送請求(反過來一樣可以。)

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