11

前言

Nginx如何处理跨域请求
(本文适用于初学者)

一、Nginx

关于Nginx的用途,听到最多的两个词,就是:

  • 端口转发
  • 负载均衡

负载均衡不属于现阶段要学习的内容,重点来看一看端口转发,本文用它来解决跨域请求的问题。

二、CROS 跨域资源共享

我们需要知道,同源的三要素:协议域名端口
如果比较两个地址,只要三者中只要有任何一个不同,就算跨域。

// 协议:http
// 域名:localhost
// 端口:8011

http://localhost:8011

出于安全原因,浏览器限制从脚本(比如JavaScript)内发起的跨源HTTP请求。
如果浏览器检测到跨域,它会尝试发起一次请求,然后查看返回的内容中,是否一个有允许跨域请求的标记(CORS响应头),如果有正确的标记,那么就不拦截;如果没有标记,浏览器就会阻止这个请求。并报错。
图片.png

三、项目中为何产生跨域

前后台分离的项目中,前台和后台分别运行在不同的端口上。

所以前台后台发起请求时,会因为跨域,而被浏览器拦截下来。

图片.png

浏览器错误信息:

这时解决方案有两个:

  • 开放跨域请求
  • 使跨域变成同源

第一种方法,显然不安全,开放跨域意味着,浏览器不再进行拦截。如果前台代码被篡改,把后台的地址指向黑客的服务器,那么会对用户造成损失。

第二种方法,想办法变成同一个域,这就轮到Nginx出场了!

四、使用Nginx转发

首先要明白,是谁把前台向后台的请求拦截下来的?不是后台,而是浏览器
如果要避免跨域,只要让浏览器认为“我正在向同一个域发起请求”,就可以了。

假设前台使用4200端口,后台使用8080端口,那么,再加入一个8011端口,作为用户访问时连接的端口。
在前台的代码中,会有拦截器,如果发现某个请求是指向后台的,就会在Url中加入一个特殊的标识(比如加一个/api/作为前缀)

// header中带有do_not_intercept,且值为true,则不添加url前缀
if (('true' !== req.headers.get(YunzhiInterceptor.DONT_INTERCEPT_HEADER_KEY))
  && !url.startsWith('https://') && !url.startsWith('http://')) {
  url = '/api/' + url;
}

现在,无论是指向前台还是后台的请求,都会发送到8011端口,只不过,指向后台的请求会有一个/api/前缀。

接下来使用Nginx监听8011端口,当接收到请求时,根据是否有前缀,来判断此请求交给前台或后台处理。

过程如图:
图片.png

上图就是转发的原理。

五、总结

使用Nginx端口转发,本质上就是:让浏览器认为前台和后台是同一个域,就不会产生跨域请求。
开发者事先约定好,根据不同的请求地址,来访问不同的服务器。
Nginx接收到数据之后,根据地址,转发给相应的服务器来处理。
如果需要另外安排其他的服务,来实现文件上传功能的话,只需要把URL处理一下,加上不同的前缀即可。


LYX6666
1.6k 声望75 粉丝

一个正在茁壮成长的零基础小白