前端頁面訪問node后端接口跨域報錯
Access to XMLHttpRequest at 'http://192.18.31.75/api/get?name=ss&age=19' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
這個報錯的意思是:你的前端頁面(http://127.0.0.1:5500)在請求后端接口(http://192.18.31.75/api/get)時,因為跨域被瀏覽器攔截了。
原因:
-
?
瀏覽器的同源策略限制了不同源(協議、域名、端口不同)的請求。
-
?
后端沒有設置?
Access-Control-Allow-Origin
?響應頭,瀏覽器就會阻止前端訪問數據。
解決方法
1. 在 Express 后端允許跨域
安裝?cors?中間件:
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
npm?install?cors
在你的?app.js
?里添加如下代碼:
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
const?cors?=?require("cors");
app.use(cors());//需要寫在路由注冊之前//有其他配置的寫法
app.use(cors({allowedHeaders: ["Content-Type", "Authorization", "token"]
}));
這樣所有接口都允許跨域訪問。
2. 手動設置響應頭(不推薦,推薦用 cors)
2.1 cors響應 Access-Control-Allow-Origin
手動設置響應頭:
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
app.use((req, res, next) => {res.setHeader("Access-Control-Allow-Origin", "*");//*也可寫成其他具體網站next();
});
使用 cors 中間件(推薦):
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
const cors = require("cors");
app.use(cors()); // 默認允許所有來源,自動設置 Access-Control-Allow-Origin: *
//或者
const cors = require("cors");
app.use(cors({origin: "http://127.0.0.1:5500" // 只允許這個來源跨域
}));
2.2 cors響應頭,Access-Control-Allow-Headers
是 CORS(跨域資源共享)中的一個響應頭,用于指定允許哪些自定義請求頭可以在跨域請求中使用。
cors僅支持客戶端向服務器發送9個請求頭,如果客戶向服務器發送了額外的請求頭信息,則需要在服務端,通過Access-Control-Allow-Headers對額外的請求頭聲明
手動設置響應頭:
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
//允許客戶端額外向服務器發送Content-Type請求頭和X-Custom-Header請求頭
res.setHeader('Access-Control-Allow-Headers','Content-Type','X-Custom-Header')
res.setHeader("Access-Control-Allow-Origin", "*");
使用 cors 中間件(推薦):
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
const cors = require("cors");
app.use(cors({allowedHeaders: ["Content-Type", "Authorization", "token"]
}));
2.3 cors響應頭,Access-Control-Allow-Methods
Access-Control-Allow-Methods
?是 CORS(跨域資源共享)中的一個響應頭,用于指定允許哪些 HTTP 方法可以進行跨域請求。
作用:
當瀏覽器發起跨域請求時,如果請求方法不是簡單的 GET/POST/HEAD,或者有自定義頭部,會先發送一個預檢請求(OPTIONS)。服務器需要通過?Access-Control-Allow-Methods
?告訴瀏覽器:哪些方法(如 GET、POST、PUT、DELETE 等)是被允許的。
常見用法:
手動設置響應頭:
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
app.use((req, res, next) => {res.setHeader("Access-Control-Allow-Origin", "*");res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");next();
});
使用 cors 中間件(推薦):
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
const cors = require("cors");
app.use(cors({methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
}));
3.jsonp
JSONP 用于解決跨域問題。 callback 是前端指定的回調函數名,后端用它把數據“包裹”起來返回,前端通過這個函數獲取數據。
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
//前端寫法
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><!-- 引入jquery線上版 --><script src="https://cdn.staticfile.net/jquery/3.7.1/jquery.min.js"></script></head><body><button id="btnjsonp">測試jsonp</button><script>$(function () {//jQuery 會自動生成類似 jQuery371013504642194028282_1754319071541 的回調名,并帶到請求里。$("#btnjsonp").on("click", function () {$.ajax({type: "GET",url: "http://192.18.31.75:80/api/jsonp",dataType: "jsonp",success: function (res) {console.log(res, "res");},});});});</script></body>
</html>
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
//node后端router.js文件
const express = require("express");
const apiRouter = express.Router();
//jsonp
// JSONP 用于解決跨域問題。
// callback 是前端指定的回調函數名,后端用它把數據“包裹”起來返回,前端通過這個函數獲取數據。
apiRouter.get("/jsonp", (req, res) => {// 這是因為你用 jQuery 的 $.ajax 或 $.getJSON 發起了 JSONP 請求,jQuery 會自動生成一個全局唯一的回調函數名(防止沖突),并把它作為 callback 參數傳給后端。// 后端收到請求后,把數據包裹在這個函數名里返回,前端就能通過這個函數拿到數據const funcName = req.query.callback;console.log("funcName", funcName); //打印結果:funcName jQuery371013504642194028282_1754319071541const data = { name: "zz", age: 11 };const scriptStr = `${funcName}(${JSON.stringify(data)})`;res.send(scriptStr);
});
module.exports = apiRouter;//app.js文件內容
const express = require("express");
const router = require("./router");
const cors = require("cors");//cors可以不用寫
const app = express();app.use(cors());//cors可以不用寫
app.use(express.urlencoded({ extended: false }));
app.use("/api", router);app.listen(80, () => {console.log("express server running at http://192.18.31.75");
});
總結:
只要后端加上 CORS 相關響應頭,前端就能正常跨域訪問接口了。推薦使用?cors
?中間件,簡單安全。
備注:注意:主要在服務器端進行配置,客戶端無需做任何配置。cors在瀏覽器中有兼容性,只有支持XMLHttpRequest Level2的瀏覽器,才能正常的訪問開了cors的服務端接口(例如:IE10+ Chrom4+ FireFox3.5+)