Nginx入门到实践:跨域 CORS 配置

2023年 7月 10日 59.6k 0

8. 跨域 CORS 配置

关于简单请求、非简单请求、跨域的概念,前面已经介绍过了,还不了解的可以看看前面的讲解。现在前后端分离的项目一统天下,经常本地起了前端服务,需要访问不同的后端地址,不可避免遇到跨域问题。

Nginx入门到实践:跨域 CORS 配置

要解决跨域问题,我们来制造一个跨域问题。首先和前面设置二级域名的方式一样,先设置好 fe.sherlocked93.clubbe.sherlocked93.club 二级域名,都指向本云服务器地址,虽然对应 IP 是一样的,但是在 fe.sherlocked93.club 域名发出的请求访问 be.sherlocked93.club 域名的请求还是跨域了,因为访问的 host 不一致(如果不知道啥原因参见前面跨域的内容)。

8.1 使用反向代理解决跨域

在前端服务地址为 fe.sherlocked93.club 的页面请求 be.sherlocked93.club 的后端服务导致的跨域,可以这样配置:

server {
  listen 9001;
  server_name fe.sherlocked93.club;

  location / {
    proxy_pass be.sherlocked93.club;
  }
}
复制代码

这样就将对前一个域名 fe.sherlocked93.club 的请求全都代理到了 be.sherlocked93.club,前端的请求都被我们用服务器代理到了后端地址下,绕过了跨域。

这里对静态文件的请求和后端服务的请求都以 fe.sherlocked93.club 开始,不易区分,所以为了实现对后端服务请求的统一转发,通常我们会约定对后端服务的请求加上 /apis/ 前缀或者其他的 path 来和对静态资源的请求加以区分,此时我们可以这样配置:

# 请求跨域,约定代理后端服务请求path以/apis/开头
location ^~/apis/ {
    # 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配
    rewrite ^/apis/(.*)$ /$1 break;
    proxy_pass be.sherlocked93.club;
  
    # 两个域名之间cookie的传递与回写
    proxy_cookie_domain be.sherlocked93.club fe.sherlocked93.club;
}
复制代码

这样,静态资源我们使用 fe.sherlocked93.club/xx.html,动态资源我们使用 fe.sherlocked93.club/apis/getAwo,浏览器页面看起来仍然访问的前端服务器,绕过了浏览器的同源策略,毕竟我们看起来并没有跨域。

也可以统一一点,直接把前后端服务器地址直接都转发到另一个 server.sherlocked93.club,只通过在后面添加的 path 来区分请求的是静态资源还是后端服务,看需求了。

8.2 配置 header 解决跨域

当浏览器在访问跨源的服务器时,也可以在跨域的服务器上直接设置 Nginx,从而前端就可以无感地开发,不用把实际上访问后端的地址改成前端服务的地址,这样可适性更高。

比如前端站点是 fe.sherlocked93.club,这个地址下的前端页面请求 be.sherlocked93.club 下的资源,比如前者的 fe.sherlocked93.club/index.html 内容是这样的:



    welcome fe.sherlocked93.club!!
    
    var xmlhttp = new XMLHttpRequest()
    xmlhttp.open("GET", "http://be.sherlocked93.club/index.html", true);
    xmlhttp.send();
    


复制代码

打开浏览器访问 fe.sherlocked93.club/index.html 的结果如下:

Nginx入门到实践:跨域 CORS 配置

很明显这里是跨域请求,在浏览器中直接访问 http://be.sherlocked93.club/index.html 是可以访问到的,但是在 fe.sherlocked93.club 的 html 页面访问就会出现跨域。

/etc/nginx/conf.d/ 文件夹中新建一个配置文件,对应二级域名 be.sherlocked93.club

# /etc/nginx/conf.d/be.sherlocked93.club.conf

server {
  listen       80;
  server_name  be.sherlocked93.club;
  
	add_header 'Access-Control-Allow-Origin' $http_origin;   # 全局变量获得当前请求origin,带cookie的请求不支持*
	add_header 'Access-Control-Allow-Credentials' 'true';    # 为 true 可带上 cookie
	add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  # 允许请求方法
	add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;  # 允许请求的 header,可以为 *
	add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
	
  if ($request_method = 'OPTIONS') {
		add_header 'Access-Control-Max-Age' 1728000;   # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
		add_header 'Content-Type' 'text/plain; ';
		add_header 'Content-Length' 0;
    
		return 204;                  # 200 也可以
	}
  
	location / {
		root  /usr/share/nginx/html/be;
		index index.html;
	}
}
复制代码

然后 nginx -s reload 重新加载配置。这时再访问 fe.sherlocked93.club/index.html 结果如下,请求中出现了我们刚刚配置的 Header:

Nginx入门到实践:跨域 CORS 配置

解决了跨域问题。

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论