Nginx 通过反向代理解决跨域问题

一、问题的由来

随着项目不断地演进,难免会涉及到微服务架构。当采用微服务架构之后,web项目自然免不了面临跨域的问题。最近学习了一下这方面的知识,做个小笔记方便以后回顾,希望各位大神多多指教。

二、跨域究竟是个什么东东

跨域问题的出现是由于浏览器出于安全而遵守一个叫做“同源策略”的约定,而限制访问不同源下的资源而导致的。具体哪些情况属于同源,可参考大神文章--“什么是同源策略”。

既然是浏览器都遵循的一个公共策略,而且是出于安全性考虑的,那么我们遇到跨域问题就要谨慎解决,不然则会导致应用安全性下降。著名的CSRF(Cross Site Request Forgery),即跨站请求伪造,

如果没有同源策略的限制的话就能轻易实现。虽然由于同源策略的限制,web应用的安全性提高了但同时也带来一些麻烦,比如我们服务器有两个端口,这时我们想在Ajax调用另一个端口的服务就不行了。

就好比中国对一些外网的IP封锁,它保护了国家重要关键信息的安全,同时也给大家查资料带来了一些麻烦。可参考大神文章--“一个解除跨域限制的浏览器有多危险”。

 

值得强调的是,跨域问题是浏览器对于访问的限制,可以通过禁用浏览器同源测略来解除限制。可参考大神文章--“禁用浏览器同源策略的方法”。

对于跨域请求,如果服务不可用的情况下,那么控制台的错误是这样的:

显示连接被拒绝了,而当服务可用的时候,控制台返回的错误是这样的:

可以发现如果没有做相应的跨域处理的话,浏览器其实是能发送这个请求的,但是当浏览器检测这是一个不被允许的跨域请求的话,则会放弃这个请求,返回失败。

在网上看到一个图很形象地描述了这一过程:

这也就说明了,跨域请求是由浏览器来拦截控制的,也就解释了简单粗暴地直接关闭浏览器的同源策略检查就能实现跨域访问的原理,但是这样就等于完全放弃了安全检查,那么该怎么办呢?

著名文学家鲁迅先生曾经说过----“只要思想不滑坡,方法总比困难多”。IP封锁阻挡不了大家查资料的热情,各种FQ软件层出不穷,当然跨域问题也是有相应的解决方案的。

三、解决跨域问题的正确姿势

解决跨域问题有很多方法,像什么jasonp、document.domain + iframe跨域、location.hash + iframe跨域、跨域资源共享(CORS)等等。每种方法都有自己的优缺点,大家可根据需求自行选择相应的解决方案,

具体可参看大神文章--“前端解决跨域的九种方法”。

我这里采用的是“nginx反向代理跨域”,即通过配置nginx代理来实现请求的转发从而实现跨域访问。相信大家都听过nginx的大名,它可以用来做静态http服务器、正反向代理、负载均衡、虚拟主机等。

使用nginx来解决跨域问题其实就是利用了其反向代理的功能。如果不清楚nginx正反向代理的同学,可参考大神文章--“Nginx的正向代理和反向代理”。

四、进入正题

当然在这之前需要大家先了解nginx的相关知识,大家可自行百度,nginx也是个好东西可以了解了解。

先用HBuilder创建一个简单的页面,两个按钮分别发送请求到Java服务器(5001端口)和.NET Core服务器(5000端口),HBuilder页面所在端口为8848。

然后创建两个api接口,一个Java的,一个.NET Core的,与之前说的端口对应上,然后开启服务,接口测试正常。没有配置nginx时访问不出意料地显示跨域错误:

接下来就是配置nginx了,安装nginx后找到配置文件nginx.conf,修改转发规则:

nginx的核心在于配置文件的编写,这里我简单地写了三条转发规则,nginx还支持更复杂的转发配置,更详细的nginx配置规则大家可自行百度学习。然后测试页面的Ajax地址做简单修改,使之与nginx的转发规则匹配:

接下来就是见证奇迹的时刻了:

访问成功了,并且可以发现返回请求的服务器类型是nginx,通过nginx将配置了转发规则的请求转发到指定服务器,而没有配置的地址还是会被浏览器拦截的,实现了安全可控的跨域访问。

好了,到这里算是完美解决了跨域问题,当然实际开发过程中还可能出现各种各样的问题,还是需要不断学习。加油,奥力给!!!

posted @ 2021-06-09 18:17  松树住松鼠  阅读(103)  评论(0编辑  收藏  举报