Skip to content

在我们前端开发的过程中, 相信大家都遇到过一个让人头疼的问题,那就是跨域问题.

跨域解决的方式有很多,这里主要讲的是如何来使用 nginx 来解决我们所遇到的跨域问题

首先,在我们开始之前,首先要知道跨域是如何产生的:

1.协议 2.ip 3.端口号

这三者有任何一个不同,就会产生跨域问题

了解了跨域的产生,接着我们就来看看,如何解决它?

一.下载 nginx

下载地址:http://nginx.org/en/download.html

如图所示, 选择相应的版本,进行下载:

img

下载完成后,选择任意位置进行解压,不需要安装

解压完成后,进入 nginx 的目录,输入命令 nginx -v 如果能够出现版本,则说明成功,如图:

img

二. nginx 反向代理解决跨域问题

1.问题的产生

在这里,我们使用 ajax 来做请求,然后 node+express 来写后台

前端代码如下所示:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>test</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  </head>
  <body>
    <button>点击</button>
    <script>
      // 给button添加点击事件
      $("button").click(function () {
        $.ajax({
          url: "localhost:3000/user/find",
          success: function (r) {
            console.log(r);
          },
          error: function (e) {
            console.log(e);
          },
        });
      });
    </script>
  </body>
</html>

后端代码,如下所示:

使用前,需要安装 express:npm install express

js
let express = require("express");
// 创建应用
let app = express();

// get请求
app.get("/user/find", (req, res) => {
  res.send("hello");
});

// 启动服务,监听端口
app.listen(3000, () => {
  console.log("启动成功...");
});

然后开启后台 node 服务

这个时候,如果打开页面访问接口,会出现跨域报错,如下图所示:CORS

注意,打开文件的时候一定要在服务中打开,不要使用绝对路径打开

 img

2.问题的解决

反向代理的意思就是把前端的地址和后端的地址 使用 nginx 转换到相同的地址下,如把上面的 node 服务

3000 端口 和 网页打开的服务 5500 端口都转换到 nginx 的 8000 端口下!

具体配置如下:

打开 nignx 底下 conf 文件夹,在 conf 文件夹中有一个 nginx.conf 文件,更改配置如下

bash
server {
        listen       8000;
        server_name  localhost;
        # / 表示匹配路径为/的url
        location / {
           proxy_pass localhost:5500;
        }

        # /user 表示访问以/user 开头 的地址 如/username,/user/find等
        location /user {
           proxy_pass localhost:3000;
        }
    }

上面代码的意思是,把访问 localhost:8000 转换成访问 localhost:5500

而访问 localhost:8000/user/* 则转换成 localhost:3000/user

配置完成之后需要在终端中,使用 nginx -s reload 更新我们的配置

启动 nginx 的命令是 start nginx

img

然后,把前端代码的请求地址修改一下,此时前端访问的就不再是 node 的服务了,而是要访问 nginx,然后通

过 nginx 做响应的转发 

js
// 给button添加点击事件
$("button").click(function () {
  $.ajax({
    url: "localhost:8000/user/find",
    success: function (r) {
      console.log(r);
    },
    error: function (e) {
      console.log(e);
    },
  });
});

在浏览器中访问的也不再是 localhost:5500 了,而是 localhost:8000

原因:

首先,跨域问题的本质是浏览器觉得不安全。跨域问题出现的基本原因是浏览器的同源策略。

同源策略是一个重要的安全策略,它限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。

所以跨域问题的错误是发生在浏览器端的。请求是可以正常从浏览器发到服务器端,服务器也可以处理请求,只是返回到浏览器端时出错了。

img

我们将前端端口 5500 映射到 nginx 的 8000 上(把前端项目部署在 nginx 上,把访问 localhost:8000 转换成访问 localhost:5500),这样浏览器就认为我们的前端项目就是运行在 8000 端口上。

我们把后端的访问端口用 nginx 做了代理,即访问 localhost:8000/user/_ 则转换成 localhost:3000/user/_。

这样前端项目在调用后端接口时,就是从浏览器的 8000 端口(因为前端项目被映射到 8000 端口上面了)出发访问后台的 8000 端口(而 nginx 去访问后台是不受端口限制的,因为服务器之间不存在跨域问题),自然不会出现跨域问题。

这样就不会出现跨域问题了,这就是反向代理!(只有代理后端才叫反向代理)

img

 

注意:

实际项目中一般会用 nginx 把前端项目部署在 80 端口,而后端项目用 dockerFile 制作镜像运行在 8080 端

口(不会把 8080 再映射到 80),最后用 docker-compose 做 nginx+springboot 的服务编排即可,跨域的问题交给后端代码进行处理!

补充:

例 1:

解决跨域时,前端项目除了以服务器方式部署(其他的 nginx 上或者 tomcat 上面),还可以在本 nginx 上以静态资源的方式部署

因为静态资源如果部署那么相当于 nginx 监听的端口(即前端项目端口)本身就是浏览器端口,那么 nginx 代理了后端端口之后,两者就是位于一个端口上面的,就是不存在跨域的

总结:和前面的跨域解决相比,只不过一个是把其他端口的前端服务映射到 nginx 上面,一个是直接用 nginx 承载前端项目,本质上前端项目都是运行在那个 nginx 监听的端口上面!

例 2:

前端项目如果已经运行在某个服务端口上(8080),可以让 nginx 直接监听那个 8080 即可,然后后台的端

口用 nginx 做反向代理映射到 8080 端口上面即可(不需要再代理前端的了)