深刻跨域問題(2) - 利用 CORS 解決跨域

閱讀目錄:

深刻跨域問題(1) - 初識 CORS 跨域資源共享javascript

深刻跨域問題(2) - 利用 CORS 解決跨域(本篇)html

深刻跨域問題(3) - 利用 JSONP 解決跨域前端

深刻跨域問題(4) - 利用 代理服務器 解決跨域java

回答問題:

在閱讀這篇文章以前,讀讀第一篇文章,效果會更好!!!回答上一篇文章的問題:node

  1. 不會觸發 預請求 ,由於是簡單的 GET 方法。
  2. 不會觸發 預請求,由於是簡單的 POST 方法,jquery 默認使用 application/x-www-form-urlencoded
  3. 會觸發 預請求 ,雖然是 POST 方法,可是 Content-Typeapplication/json 。並不是上文中的三種狀況,text/plainmultipart/form-dataapplication/x-www-form-urlencoded

第三點,是最重要的一點,也是常常出錯的一點,記住觸發預請求三種狀況 !!!jquery

搭建跨域環境:

模擬客戶端請求:ios

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Ajax測試</title>
</head>
<body>
    <script src="./node_modules/jquery/dist/jquery.min.js"></script>
    <script> $.ajax({ url: "http://localhost:3000", type: "get", success: function (result) { console.log(result); }, error: function (msg) { console.log(msg); } }) </script>
</body>
</html>
複製代碼

後文,將再也不粘貼 html 代碼,jquery 也能夠用 npm install jquery 下載。ajax

模擬服務器響應,新建 app.js 文件,粘貼並運行npm

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.end("{name: 'BruceLee', password: '123456'}");
        }
        
        if (request.method === 'POST') {
            response.end("true");
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});
複製代碼

好了,如今雙擊打開 html 文件,就成了:json

很明顯,這就是跨域報錯。

處理非預請求

在上述兩個例子中,咱們說到,POST 和 GET 方法,均可以實現,非預請求。

關鍵代碼:設置一條 響應首部字段,容許 CORS 跨域資源共享:

response.writeHead(200, {
  'Access-Control-Allow-Origin': '*
}
複製代碼

這裏,咱們設置爲,全部客戶端均可以訪問。

完整代碼:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*' // 關鍵代碼
            });
            
            response.end("{name: 'BruceLee', password: '123456'}");
        }
        
        if (request.method === 'POST') {
            
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*' // 關鍵代碼
            });
            
            response.end("true");
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});
複製代碼

前端測試代碼:

$.ajax({
    url: "http://localhost:3000",
    type: "get",
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})


var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    data: JSON.stringify(data),
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})
複製代碼

執行結果:

GET方法請求結果

POST方法請求結果

處理 非預請求 就是這麼簡單,只須要在後臺設置,一條 響應首部字段 便可。

注意:咱們使用 POST 方法時,Jquery 默認使用的 Content-Type: application/x-www-form-urlencoded,因此不會觸發預請求 !!!

事實上,不單單是 Jquery ,axios 等封裝 Ajax 的庫,都默認採用 Content-Type: application/x-www-form-urlencoded !!!

處理 POST 預請求

不單單是 POST ,全部 預請求 的處理方式都同樣。

POST 方法在設置 contentTypeapplication/json 時會觸發預請求。

前端測試代碼:

var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    data: JSON.stringify(data),
    contentType: 'application/json;charset=utf-8',
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})
複製代碼

注意,這裏的 contentType 已經修改成 application/json ,這種狀況是會觸發 預請求 的 ! ! !

node 服務端代碼:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });
            response.end("{name: 'BruceLee', password: '123456'}");
        }

        if (request.method === 'POST') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });

            response.end( JSON.stringify({state: true}) );
        }

        if (request.method === 'OPTIONS') {	
    		
            response.end( JSON.stringify({state: true}) );
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});
複製代碼

在這裏,咱們增長了處理 OPTIONS 方法的邏輯。

測試結果:

很明顯,咱們在 OPTIONS 方法內部沒有設置 CORS 響應首部字段 ,因此出現跨域錯誤;

修改代碼,關鍵代碼:

if (request.method === 'OPTIONS') {	
    response.writeHead(200, {
        'Access-Control-Allow-Origin': '*',	 // 設置 optins 方法容許全部服務器訪問 
        'Access-Control-Allow-Methods': '*', // 容許訪問 POST PUT DELETE 等全部方法 
    });		
    response.end( JSON.stringify({state: true}) );
}
複製代碼

在 node 代碼中,咱們增長對 OPTIONS 的處理,而且設置容許訪問, POST 方法。

修改代碼後,重啓服務器,並刷新 html 頁面,結果爲:

在這裏,仍然是有問題,按照報錯描述,咱們應該設置 Access-Control-Allow-Headers 響應首部字段 。

關鍵代碼:

if (request.method === 'OPTIONS') {	
    response.writeHead(200, {
        'Access-Control-Allow-Origin': '*',	 // 設置 optins 方法容許全部服務器訪問 
        'Access-Control-Allow-Methods': '*', // 容許訪問路徑 '/' POST等全部方法
        'Access-Control-Allow-Headers': 'Content-Type',	// 容許類 Content-Type 頭部 
    });	
    response.end( JSON.stringify({state: true}) );
}
複製代碼

咱們須要設置,容許使用頭部爲 Content-Type 的內容訪問。

完整代碼:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });
            response.end("{name: 'BruceLee', password: '123456'}");
        }

        if (request.method === 'POST') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });

            response.end( JSON.stringify({state: true}) );
        }

        if (request.method === 'OPTIONS') {	
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*',	 // 設置 optins 方法容許全部服務器訪問 
                'Access-Control-Allow-Methods': '*', // 容許訪問路徑 '/' POST等全部方法
                'Access-Control-Allow-Headers': 'Content-Type',	// 容許類 Content-Type 頭部 
            });
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});
複製代碼

執行結果:

  1. 預請求

  2. POST 請求

這樣就完成,對 預請求 的處理。如今你能夠狠狠地告訴後臺:是你沒有處理 OPTIONS 方法 !!!

好了,到這裏,知道了基礎的 預請求 處理的解決辦法了。

總結:

  1. 使用 CORS 跨域資源共享,是須要分紅 預請求非預請求 處理的。

  2. 非預請求,在服務器內,只須要簡單設置:

    'Access-Control-Allow-Origin': '* 複製代碼
  3. 預請求,在服務器內,至少要設置三個 響應首部字段

    'Access-Control-Allow-Origin': ?,	  
    'Access-Control-Allow-Methods': ?, 
    'Access-Control-Allow-Headers': 'Content-Type',
    複製代碼
  4. 前端使用 content-Type: application/json 的時候,必須注意這是 預請求 ,後端須要處理 OPTIONS 方法

參考與鳴謝:

祝你們編碼愉快,喜歡的話點個贊再走唄!!!

相關文章
相關標籤/搜索