摘自:https://segmentfault.com/a/1190000022415375
一、Nginx
关于Nginx的用途,听到最多的两个词,就是:
- 端口转发
- 负载均衡
负载均衡不属于现阶段要学习的内容,重点来看一看端口转发,本文用它来解决跨域请求的问题。
二、CROS 跨域资源共享
我们需要知道,同源的三要素:协议、域名、端口。
如果比较两个地址,只要三者中只要有任何一个不同,就算跨域。
// 协议:http
// 域名:localhost
// 端口:8011
http://localhost:8011
出于安全原因,浏览器限制从脚本(比如JavaScript)内发起的跨源HTTP请求。
如果浏览器检测到跨域,它会尝试发起一次请求,然后查看返回的内容中,是否一个有允许跨域请求的标记(CORS响应头),如果有正确的标记,那么就不拦截;如果没有标记,浏览器就会阻止这个请求。并报错。
三、项目中为何产生跨域
在前后台分离的项目中,前台和后台分别运行在不同的端口上。
所以前台向后台发起请求时,会因为跨域,而被浏览器拦截下来。
浏览器错误信息:
这时解决方案有两个:
- 开放跨域请求
- 使跨域变成同源
第一种方法,显然不安全,开放跨域意味着,浏览器不再进行拦截。如果前台代码被篡改,把后台的地址指向黑客的服务器,那么会对用户造成损失。
第二种方法,想办法变成同一个域,这就轮到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端口,当接收到请求时,根据是否有前缀,来判断此请求交给前台或后台处理。
过程如图:
上图就是转发的原理。
五、总结
使用Nginx端口转发,本质上就是:让浏览器认为前台和后台是同一个域,就不会产生跨域请求。
开发者事先约定好,根据不同的请求地址,来访问不同的服务器。
Nginx接收到数据之后,根据地址,转发给相应的服务器来处理。
如果需要另外安排其他的服务,来实现文件上传功能的话,只需要把URL处理一下,加上不同的前缀即可。