场景描述
我们要做一款B/S架构的产品,前端网页使用vue进行开发,后端服务器使用c++进行开发,前端页面通过nginx部署出去,后端服务器直接挂在公网服务器上
但是我们在测试使用的时候,出现了跨域的问题,我们第一版的解决方式,是在服务器http的应答包头部增加允许跨域字段,来解决跨域问题,但是我们在开发过程中,通过测试发现加应答头字段这种方式解决跨域在Chrome浏览器上是好使的,可以进行请求数据的正常发送和应答的,但是换用edge浏览器或者苹果浏览器,就不可以进行请求的正常收发了
随后我们了解到,通过添加http头部字段的方式,并不能完全解决这个跨域的问题(后面有说为什么不能解决),通过学习和请教了解到,可以通过nginx配置代理来解决跨域的问题,所以我们第二版的解决方式,是通过nginx配置代理的方式来解决跨域问题
现在,大家应该是了解了整个场景,下面我会分别来说一下这两种解决方式
在说这两种解决方式之前,先来说一下什么是跨域问题
跨域
你所访问的地址是分成三部分的
上面这三个部分,如果有任意一部分不一样就属于跨域
下表,就说明了常见的几种跨域情况
from | to | 是否跨域:原因 |
---|---|---|
https://www.csdn.net:443 | https://www.baidu.com | 跨域:不同的域名 |
同上 | https://csdn.net:443 | 跨域:不同的子域 |
同上 | https://mp.csdn.net:443 | 跨域:不同的子域 |
同上 | http://www.csdn.net:443 | 跨域:不同的协议类型 |
同上 | https://www.csdn.net:80 | 跨域:不同的端口号 |
同上 | https://www.csdn.net:443 | 没跨域:两个地址完全相同 |
同上 | https://www.csdn.net | 没跨域:隐式端口匹配,不是跨域 |
浏览器阻止跨域访问的原因,主要是为了安全考虑,如果没有跨域的话,你的请求可能发送到的不是你后台对应的服务器上,而是一个要获取你信息的地方,虽然添加跨域使用户的信息安全性提高了,但是对于开发来说,却带来了一定的麻烦,所以就出现了一系列跨域问题的解决方案,具体怎么解决我们接着往下看
跨域问题解决方案
服务器http应答包添加允许跨域字段解决跨域问题
在解决问题之前,我们先来说一下,浏览器是如何来进行跨域访问的,当你有请求要发给服务器时,首先如果浏览器检测到当前的访问属于跨域访问的话,浏览器不会直接发送请求,而是先发送一个不带有任何数据和认证信息的OPTIONS请求,然后浏览器会看这个请求,对应服务器回应的应答包里面的字段,如果里面存在允许跨域的字段,则浏览器才真的会把真正的请求数据发送到服务器上,如果返回的应答包中没有允许跨域字段或者浏览器依然认为发送跨域请求是不安全的,则就不会将真正的请求数据发送到服务器上。
这种解决方式比较简单,主要就是在服务器的应答包里面加上允许跨域的字段就可以了。
下面是用c++语言实现的允许跨域的应答字段代码
// 解决跨域问题 result += "Access-Control-Allow-Origin: *\r\n"; result += "Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE\r\n"; result += "Access-Control-Max-Age: 3600\r\n"; result += "Access-Control-Allow-Headers: *\r\n"; result += "Access-Control-Allow-Credentials: true\r\n";
通过这种方式来解决跨域问题,可能不一定有效,对于浏览器认可这些跨域字段的话,就可以进行数据的正常收发,但是如果浏览器依然认为这种操作是不安全的话,则所有的请求还是不能发送到服务器上,就像我之前说的一样添加允许跨域字段chrome浏览器好使,但是edge浏览器不好使,可能就是这种机制导致的。
服务器通过nginx配置代理来解决跨域问题
这第二种解决方式就是通过nginx做代理的方式,来解决跨域的问题
通过上面的几种跨域访问方式,我们可以知道,只有当源地址到目标地址那三个部分没有变化的话才是同源也就是不会产生跨域问题。可能大家还是没有理解,我们来详细说一下:就是当你的源地址是https://www.csdn.net:443/login访问的目标地址是https://www.csdn.net:443/user向这种情况进行访问时就不属于跨域,但是如果目标地址是https://www.csdn.net:8080/user时这就是跨域问题了。
所以我们通过代理的方式来解决跨域问题,实际上就是让浏览器认为我们访问的地址属于是同源地址也就不存在跨域的问题,然后这个目标地址我们通过nginx进行代理,让来自这个端口并且url为特定值的数据转发给nginx服务器上代理的ip地址以及端口,这样就解决了跨域问题。
原理如下图所示:
下面我会给出一个nginx的部分配置文件,在此之前先介绍一下我们的实际环境,来方便大家更好的理解代码:前端页面通过使用nginx代理80端口使得公网可以访问,服务器运行在服务器的9668端口上
server { listen 80; # web访问端口 error_page 404 /index.html; client_max_body_size 100m; location / { root /root/projects/web/dist; # 前端代码文件位置 index index.html; try_files $uri $uri/ /index.html; # 解决vue刷新404的问题 } location /api/ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Headers' 'X-Requested-With'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; add_header 'Cache-Control' 'no-cache'; if ($request_method = 'OPTIONS') { return 200; } proxy_pass http://127.0.0.1:9668/; # 反向代理到我们的服务器端口 # rewrite ^/b/(.*)$ /$1 break; } }
从上面的nginx配置我们可以看出,页面是直接通过80端口进行访问的,而如果页面要和服务器进行通信的话就只需要在80端口后面加上api的url就可以了,因为当nginx检测到后面的url就会将数据转发到我们9668端口的服务器上。
需要注意的是,上面只是nginx中前端页面访问和配置代理的部分配置代码,并不是完整部分
到这里后端服务器解决跨域问题就介绍完了
感谢观看学习,大佬们多多指点,愿明天的自己会感谢当下的努力!!!!