前端、node跨域问题

前端页面访问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_1754319071541
  const 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+)

相关推荐
阿里小阿希1 小时前
Vue3 + Element Plus 项目中日期时间处理的最佳实践与数据库设计规范
数据库·设计规范
白鹭2 小时前
MySQL源码部署(rhel7)
数据库·mysql
666和7773 小时前
Struts2 工作总结
java·数据库
还听珊瑚海吗3 小时前
SpringMVC(一)
数据库
星期天要睡觉4 小时前
MySQL 综合练习
数据库·mysql
Y4090014 小时前
数据库基础知识——聚合函数、分组查询
android·数据库
JosieBook5 小时前
【数据库】MySQL 数据库创建存储过程及使用场景详解
数据库·mysql
处女座_三月5 小时前
改 TDengine 数据库的时间写入限制
数据库·sql·mysql