nginx配置解决跨域访问的方法详解

 更新时间:2023年10月22日 14:21:54   作者:唯之为之  
这篇文章主要为大家详细介绍了nginx如何配置解决跨域访问的方法,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以跟随小编一起学习一下

后端环境

正常访问端口8058

经过nginx配置(文末具体展示)后,去除端口,如下:

前端开发环境

1. 配置开发和生产的环境变量

.env.development文件

# API服务路径
VITE_APP_BASE_URL = ""

.env.production文件

# API服务路径,注意没有端口号,是经过nginx处理后的后端服务地址
VITE_APP_BASE_URL = "http://192.168.1.4/"

2. vite.config.ts 文件配置开发代理

import { warpperEnv } from "./build";
import { UserConfigExport, ConfigEnv, loadEnv } from "vite";

/** 当前执行node命令时文件夹的地址(工作目录) */
const root: string = process.cwd();

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
  const { VITE_CDN, VITE_PORT, VITE_COMPRESSION, VITE_PUBLIC_PATH } =
    warpperEnv(loadEnv(mode, root));
  return {
    base: VITE_PUBLIC_PATH,
    root,
    resolve: {
      alias
    },
    // 服务端渲染
    server: {
      // 是否开启 https
      https: false,
      // 端口号
      port: VITE_PORT,
      host: "0.0.0.0",
      // 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
      proxy: {
        "^/api": {
          target: "http://192.168.1.4:8058",
          changeOrigin: true,
          rewrite: path => path.replace(/^\/api/, "")
        }
      }
    },
    // 后面省略...
  }
};

3. http 文件封装 axios,使用环境变量配置的基础API路径

// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
  // 请求地址
  baseURL: import.meta.env.VITE_APP_BASE_URL,
  // 请求超时时间
  timeout: 5000,
  headers: {
    Accept: "application/json, text/plain, */*",
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest"
  }
};

4. api 文件里使用示例

import { http } from "@/utils/http";

export type UserResult = {
  success: boolean;
  data: {
    username: string;
    roles: Array<string>;
    accessToken: string;
    refreshToken: string;
    expires: Date;
  };
};

/** 登录 */
export const getLogin = (data?: object) => {
  return http.request<UserResult>("post", "/api/login", { data });
};

5. 开发环境项目预览

由于使用了代理,所以不会有跨域的问题,如图:

前端生产环境

生产环境采用Tomcat,前端项目打包好后,放在Tomcat的 webapps/ROOT 目录下即可,如图:

启动Tomcat,双击 apache-tomcat-8.5.93/bin/ 目录下的 startup.bat,linux机器到 bin 目录下,运行 ./startup.sh

访问,Tomcat默认端口为8080,访问后台接口报跨域错误

nginx配置后,去除端口,访问正常

nginx配置

以上可以看出,nginx配置的目的,就是去除前后端的端口差异,从而解决跨域的问题。配置文件 nginx/conf/nginx.conf 修改如下:

server {
  listen       80;
  # IP/域名都可以
  server_name  http://192.168.1.4;
  #charset koi8-r;
  #access_log  logs/host.access.log  main;
  
  location / {
    root   html;
    index  index.html index.htm;
    proxy_pass http://192.168.1.4:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_connect_timeout 5;
  }
  
  location ^~ /api/ {
    add_header 'Access-Control-Allow-Origin' $http_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 204;
    }
    proxy_pass http://192.168.1.4:8058/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_connect_timeout 5;
  }
}

疑问解答

1. 此示例项目,本地模拟的线上环境,操作系统 windows,后端服务 nodejs。换成 linux 系统或其他后端服务(如:SpringBoot 等)还适用吗,为什么?

答:同样适用。

因为跨域问题是浏览器为了安全保证,当你前端服务访问跨域资源时,被浏览器默认禁止了,所以和后端服务是什么,没有必然关系;所以解决问题的思路也是让我们的访问请求,达到浏览器的要求,即不跨域(同一域名/IP、端口、协议),那当然使用 nginx 就可以。

2. 前端请求里的代理里的 ^api,和nginx配置里的 ^~ /api/ 有什么关系?

答:有关系,但是不是你想象的关系。

首先我们要确认,你的实际的请求地址里,其实不包含 api 这段路径。如图:

开发环境加这个只是为了代理区分,因为你可能要请求多个不同域名的后端服务:我可以在 vite.config.ts 文件的 proxy 里再加一个以 ^/auth 开头的,导向其他域名的后端服务。

其次代码里也可以看到 rewrite: path => path.replace(/^\/api/, ""),所以实际的请求地址,最终是去掉了 api

那为什么nginx里要配置成 api 呢?

因为线上环境是没有运行代理的,也就是说 rewrite: path => path.replace(/^\/api/, "") 这一段是没有生效的,那你前端实际的请求地址就是 http://192.168.1.4/api/login,而真正的地址里没有 api 这一段,所以多出来的这一段,正好让nginx去代理,^~ /api/ 变成 http://192.168.1.4:8058/,从而使请求地址变成 http://192.168.1.4:8058/login

3. 接上,这两 api 虽然不是我想象的关系,但是事实上必须保持一致,有没有什么可以解耦的办法?

答:有。

nginx一般不会去随便改动,所以我们的解决办法优先放在前端,让前端去适配nginx。

参考 vite.config.ts 文件的代理地址替换,那我们在实际请求地址时,也可以做一个替换处理:在 http 文件里的请求拦截器中,判断是否生产环境,如果是,则替换 ^api 为nginx配置的开头路径即可。

4. 接上,vite.config.ts 可以配置多个代理,nginx也可以配置多个后端服务,但是 http 文件里的 axios 封装只有一个 baseURL?

答:不是有拦截器吗。

env 环境配置里增加多个域名字段,假如以 auth 开头是另一个域名,那就在拦截器里使用条件判断,如果是 auth 开头,修改 config.baseURL 地址。

或者封装多个 axois?不建议,代码重复率又高了。

5. 既然nginx已经把 api 开头的都代理到了后端服务,那我前端就不能有 api 开头的路由?

答:可以。

看看访问路径,前端是哈希路由,有 # 号分隔的。如果是 history 路由呢,有试过的同学可以在评论区吱个声。

到此这篇关于nginx配置解决跨域访问的方法详解的文章就介绍到这了,更多相关nginx解决跨域访问内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 利用Nginx实现资源代理和接口代理的实现方法

    利用Nginx实现资源代理和接口代理的实现方法

    在 Web 开发与部署中,我们常常需要借助 Nginx 实现接口代理和静态资源代理,以解决跨域、统一入口、权限控制或性能优化等问题,本指南将全面介绍 Nginx 资源代理与接口代理的实现方法,需要的朋友可以参考下
    2025-04-04
  • Nginx重定向后请求参数丢失的原因分析及解决方案

    Nginx重定向后请求参数丢失的原因分析及解决方案

    在日常开发和运维中,我们经常会遇到需要使用 Nginx 进行反向代理的场景,但在配置 proxy_pass 时,有时候可能会遇到请求参数丢失的问题,在这篇文章中,我们将会详细探讨这个问题并给出几种解决方案,需要的朋友可以参考下
    2023-11-11
  • nginx对http请求处理的各个阶段详析

    nginx对http请求处理的各个阶段详析

    这篇文章主要给大家介绍了关于nginx对http请求处理的各个阶段分析的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • nginx中的正则表达式及location和rewrite总结

    nginx中的正则表达式及location和rewrite总结

    rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向,这篇文章主要介绍了nginx中的正则表达式及location和rewrite总结,需要的朋友可以参考下
    2023-12-12
  • nginx中常见日志分析命令合集

    nginx中常见日志分析命令合集

    这篇文章主要为大家整理了一些nginx中常见日志分析命令,例如 查看实时日志,统计状态码分布,分析客户端 IP等,有需要的小伙伴可以参考一下
    2025-05-05
  • Nginx实现http自动跳转到https

    Nginx实现http自动跳转到https

    本文主要介绍了Nginx实现http自动跳转到https,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 基于nginx的静态网页部署的实现

    基于nginx的静态网页部署的实现

    这篇文章主要介绍了基于nginx的静态网页部署的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • Nginx为已安装nginx动态添加模块

    Nginx为已安装nginx动态添加模块

    本篇文章主要介绍了Nginx之为已安装nginx动态添加模块的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • Nginx常用配置以及代理转发操作详解

    Nginx常用配置以及代理转发操作详解

    这篇文章主要给大家介绍了关于Nginx常用配置以及代理转发的相关资料,nginx一般被用来做反向代理,将请求转发到应用服务器上,比如tomcat的应用,需要的朋友可以参考下
    2023-09-09
  • 深入理解Nginx之error_page模块的使用

    深入理解Nginx之error_page模块的使用

    error_page是nginx一个重要的指令,作用是定制化服务器错误页面,本文主要介绍了Nginx之error_page模块的使用,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09

最新评论