当前位置: 首页 > 知识库问答 >
问题:

vue.js - Docker启动的Nginx如何解决浏览器跨域问题?

方河
2023-12-27

Nginx如何解决跨域问题

问题简述:

docker启动的nginx,修改配置文件default.conf,允许跨域不生效。
平台:MacOS M1pro

问题描述:

我使用Vue实现了一个前端项目,使用Nginx静态资源代理监听80端口,向本地后端服务http://localhost:9000/发送Get请求

// 跨域访问后端项目axios.get("http://localhost:9000/hello")    .then(function (response) {      console.log(response)    })

go语言实现的后端项目核心代码,启动服务监听9000端口

func handler(w http.ResponseWriter, r *http.Request) {    _, err := fmt.Fprintf(w, "Hello, 第一条消息")    if err != nil {        return    }}func main() {    http.HandleFunc("/hello", handler)    err1 := http.ListenAndServe(":9000", nil)    if err1 != nil {        return    }}

将Vue项目打包为dist,复制到docker容器的/usr/share/nginx/html目录中,配置文件为:

server {    listen       80;    listen  [::]:80;    server_name  localhost;    #access_log  /var/log/nginx/host.access.log  main;    location / {        #允许跨域请求的域,* 代表所有        add_header 'Access-Control-Allow-Origin' *;        root   /usr/share/nginx/html;        index  index.html index.htm;    }    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }}

启动过程略过,可以发现跨域错误
image.png
直接使用浏览器访问9000端口是正常的:
image.png

如何在Nginx解决跨域问题,我已经了解前端虚拟代理、后端允许跨域方法。
本问题只讨论nginx如何允许跨域。
已经尝试的方法如下,已确定修改配置文件后重启nginx。

方法一:

    #access_log  /var/log/nginx/host.access.log  main;    location / {        root   /usr/share/nginx/html;        index  index.html index.htm;        #允许跨域请求的域,* 代表所有        add_header 'Access-Control-Allow-Origin' *;    }

方法二:

    location / {        add_header Access-Control-Allow-Origin *;        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';        add_header 'Access-Control-Allow-Credentials' 'true';         if ( $request_method = 'OPTIONS' ) {             return 200;         }        root   /usr/share/nginx/html;        index  index.html index.htm;    }

方法三:增加always

    location / {        add_header Access-Control-Allow-Origin * always;        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;        add_header 'Access-Control-Allow-Credentials' 'true' always;         if ( $request_method = 'OPTIONS' ) {             return 200;         }        root   /usr/share/nginx/html;        index  index.html index.htm;    }

网络上可以直接搜索到的方法基本都尝试过,求大佬解答,并进一步讨论相关理论(从Nginx实现方法角度)
特别强调,本项目使用Docker启动容器,因此容器向localhost分发流量的域名为host.docker.internal

共有2个答案

温亮
2023-12-27

假如我有一个网站 www.simple.com ,这个对应一个静态的html网站。
还有一个API域名 api.simple.com ,这个对应后端的API接口。

假如我在www.simple.com这个网站内,去调用 api.simple.com 这个域名的接口,这个时候,在没有任何配置的情况下,两个域名不一致,浏览器就会提示跨域,阻止访问api.simple.com这个域名的接口访问。

浏览器怎么去验证是否跨域,当浏览器发现 不是同源的请求,就会发起一个 OPTIONS 请求给被访问的接口,只有接口返回了同意跨域 (Access-Control-Allow-Origin/Methods/Headers) ,浏览器才会放行这个跨域请求。

所以解决跨域的唯一方法,就是被访问的一方,设置请求头,允许被跨域访问。

你这里的配置文件,我看到都是在给 html 设置同意跨域,而不是在给接口设置同意跨域。


nginx 设置允许跨域,就是用add_header这个指令,添加允许跨域的请求头。
跨域问题,应该和nginx是不是在容器内运行,没有任何关系,它只和接口的OPTIONS响应有关系,响应是允许那么就可以跨域,响应是不允许,那么就不可以跨域。


如果你要用nginx解决跨域,配置可能这两种会比较常见:
(随手写的例子,不一定能跑,意思到了就行)
第一种方式:

server {    listen 80;    server_name www.simple.com; # 用一个域名部署前端项目    location / {        root   /usr/share/nginx/html;        index  index.html index.htm;    }}server {    listen 80;    server_name api.simple.com;  #单独用一个api域名代理到后端,并设置允许跨域    location / {        proxy_pass http://127.0.0.1:8080;         add_header 'Access-Control-Allow-Origin' 'http://www.simple.com';  # 允许www.simple.com跨域    }}

第二种方式:

server {    listen 80;    server_name www.simple.com;    # 这里前端和后端api都使用同一个域名访问,就没有跨域的问题了。    location / {        root   /usr/share/nginx/html;        index  index.html index.htm;    }    location /api {        proxy_pass http://127.0.0.1:8080;     }}
封景曜
2023-12-27

首先,让我们理解一下跨域资源共享(CORS)的基本概念。当一个网页想要从不同的源(域名、协议或端口)获取资源时,它就会遇到跨域问题。这是因为出于安全原因,浏览器会阻止这种类型的请求。为了解决这个问题,服务器需要明确地允许这种跨域请求。

在你的情况下,Nginx服务器被用作反向代理,所以实际上是由后端服务器(可能是由Go语言实现的)来处理请求和响应的。浏览器发送的跨域请求首先到达Nginx,然后Nginx将请求转发给后端服务器。因此,需要后端服务器允许跨域,而不是Nginx。

你尝试的方法都是在Nginx的配置中添加add_header指令来允许跨域,但这是不正确的。实际上,Nginx本身并不处理跨域问题,它只是将请求转发给后端服务器。解决这个问题需要在后端服务器上设置适当的CORS策略。

如果你使用的是Go语言,你可以使用标准的Go库来处理CORS,例如:

package mainimport ( "net/http" "os")func main() { http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") if origin != "" { w.Header().Set("Access-Control-Allow-Origin", origin) } else { w.Header().Set("Access-Control-Allow-Origin", "*") } w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range") w.Header().Set("Access-Control-Allow-Credentials", "true") w.Write([]byte("Hello, World!")) }) http.ListenAndServe(":9000", nil)}

这段代码会在响应头中设置适当的CORS策略。这样,当Nginx将请求转发给这个Go程序时,浏览器就不会再因为跨域问题而阻止请求了。

 类似资料:
  • 本文向大家介绍C#浏览器提示跨域问题解决方案,包括了C#浏览器提示跨域问题解决方案的使用技巧和注意事项,需要的朋友参考一下 一,我们使用两个域名互相访问的时候会提示跨域,原因在哪里呢?如下图跨域,我们探究下 是什么原因导致浏览器报这个错呢? 二,我们研究下看看请求是否成功。,如下图,浏览器返回的是200,证明请求是成功了,同时返回是成功了,那为什么还提示跨域呢? 三,经过看浏览器跨域的提示可知道“

  • 本文向大家介绍如何用Nginx解决前端跨域问题,包括了如何用Nginx解决前端跨域问题的使用技巧和注意事项,需要的朋友参考一下 前言 在开发静态页面时,类似Vue的应用,我们常会调用一些接口,这些接口极可能是跨域,然后浏览器就会报cross-origin问题不给调。 最简单的解决方法,就是把浏览器设为忽略安全问题,设置--disable-web-security。不过这种方式开发PC页面到还好,如

  • 本文向大家介绍vue.js使用代理和使用Nginx来解决跨域的问题,包括了vue.js使用代理和使用Nginx来解决跨域的问题的使用技巧和注意事项,需要的朋友参考一下 使用Nginx 反向代理解决跨域问题(vue.js使用代理去掉vue.js因为跨域而触发的options请求) 我们的项目还是需要node.js作为容器的 一、Windows 下安装Nginx (官网下载稳定版http://ngin

  • 我们在部署之后, 会发现Vuejs会遇到js 的经典问题: 远程服务器地址不对,或者跨域问题. 前提: 我们的真正后台接口是: http://siwei.me/interface/blogs/all 如下: 域名404 问题 这个问题看起来如下: 这个问题是由于源代码中,访问 /interface/blogs/all 这个接口引起的: this.$http.get('/api/interface/

  • vue2调试h5预览pdf的问题? pdf地址 http://www.xxxx.org.cn/TrendFile/YB_SD_HJ_1mon_20231125_SDMF.pdf 在谷歌浏览器里面可以直接预览,但是放到本地vue的代码里面会报错跨域,iframe也会报错跨域,有什么方法可以正常预览 把静态pdf文件放到static 或者asset文件夹下 通过路径预览,会出现 404的问题 求教该如

  • 本文向大家介绍Nginx解决转发地址时跨域的问题,包括了Nginx解决转发地址时跨域的问题的使用技巧和注意事项,需要的朋友参考一下 一、什么是跨域问题 在一个服务器A里放置了json文件,另一个服务器B想向A发送ajax请求,获取此文件,会发生错误。 Chrome提示: 这就是跨域问题。解决方案有不少,比较好的是服务器端配置CORS,但要求服务器端做更改。如果在不需要更改服务器端的情况下解决呢?尤