深入跨域问题(2) - 利用 CORS 解决跨域
閱讀目錄:
深入跨域問題(1) - 初識 CORS 跨域資源共享;
深入跨域問題(2) - 利用 CORS 解決跨域(本篇)
深入跨域問題(3) - 利用 JSONP 解決跨域
深入跨域問題(4) - 利用 代理服務器 解決跨域
回答問題:
在閱讀這篇文章之前,讀讀第一篇文章,效果會更好!!!回答上一篇文章的問題:
第三點,是最重要的一點,也是經常出錯的一點,記住觸發預請求三種情況 !!!
搭建跨域環境:
模擬客戶端請求:
<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 下載。
模擬服務器響應,新建 app.js 文件,粘貼并運行 :
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 文件,就成了:
很明顯,這就是跨域報錯。
處理非預請求
在上述兩個例子中,我們說到,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);} }) 復制代碼執行結果:
處理 非預請求 就是這么簡單,只需要在后臺設置,一條 響應首部字段 即可。
注意:我們使用 POST 方法時,Jquery 默認使用的 Content-Type: application/x-www-form-urlencoded,所以不會觸發預請求 !!!
事實上,不僅僅是 Jquery ,axios 等封裝 Ajax 的庫,都默認采用 Content-Type: application/x-www-form-urlencoded !!!
處理 POST 預請求
不僅僅是 POST ,所有 預請求 的處理方式都一樣。
POST 方法在設置 contentType 為 application/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'); }); 復制代碼執行結果:
預請求
POST 請求
這樣就完成,對 預請求 的處理。現在你可以狠狠地告訴后臺:是你沒有處理 OPTIONS 方法 !!!
好了,到這里,知道了基礎的 預請求 處理的解決辦法了。
總結:
使用 CORS 跨域資源共享,是需要分成 預請求 與 非預請求 處理的。
非預請求,在服務器內,只需要簡單設置:
'Access-Control-Allow-Origin': '* 復制代碼預請求,在服務器內,至少要設置三個 響應首部字段:
'Access-Control-Allow-Origin': ?, 'Access-Control-Allow-Methods': ?, 'Access-Control-Allow-Headers': 'Content-Type', 復制代碼前端使用 content-Type: application/json 的時候,必須注意這是 預請求 ,后端需要處理 OPTIONS 方法
參考與鳴謝:
- 跨域資源共享 CORS 詳解 阮一峰;
- 瀏覽器同源政策及其規避方法 阮一峰;
- HTTP訪問控制 (CORS) MDN 文檔;
祝大家編碼愉快,喜歡的話點個贊再走唄!!!
總結
以上是生活随笔為你收集整理的深入跨域问题(2) - 利用 CORS 解决跨域的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Excel vba引用工作表的三种写法
- 下一篇: redis学习之redis基本数据类型以