这是我参与「第四届青训营 」笔记创作活动的第4天
前言
在开发前后端分离的网页应用时,有一个问题是经常发生的,那就是跨域。屏幕前的你,一定在浏览器的控制台看到过这种界面吧:
那造成这种现象的原因是什么呢?又该如何解决呢?
什么是同源与跨域?
同源策略: 同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
同源的定义: 如果两个 URL 的 protocol、port(如果有指定的话) 和 host都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。
所以说,协议,主机,端口三者缺一不可,但是在前后端分离的开发过程中,前端和后端往往是运行在不同的运行时上的,所以端口就不会相同,跨域问题就产生了。
解决方案
既然知道了原理,那该如何解决呢?
CORS跨域资源共享
简而言之,就是在服务端允许的情况下,让浏览器可以进行跨域访问。
缺点:配置较为复杂,且如果允许全部跨域请求,也会导致不安全的因素产生。
请求代理
那有没有一种更简单的方案呢,有!那就是代理!
在计算机网络中,我们就学习到了代理的相关知识,比如NAT,就是通过代理,使得一个IP的用途增加的方式。简而言之,代理可以通过识别请求的特征,将请求转发给其他的地址,再在其他地址得到相应后,将数据返回。根据可见性,我们又将代理分为两类,正向代理和反向代理。
服务端配置:反向代理
反向代理是指代理发生在服务器端,例如NGINX就是一个典型的提供反向代理的服务器。这种代理对客户端是透明的。如图,在客户端看来,所有的请求都发到了NGINX上,也由NGINX返回,自然是同源的。
我们项目的部分NGINX配置如下:
server {
listen 80;
server_name vue;
# 用于 vue 页面
location / {
autoindex on;
root /usr/share/nginx/html; # /usr/share/nginx/html docker容器里面的目录
try_files $uri $uri/ /index.html; #history 模式
index index.html index.htm;
}
# 用于 接口 访问
location /api/ {
proxy_pass http://node:3000/; # 绝对路径,将 ip:80/api/xx 转发到 ip:8080/xx 上去
proxy_redirect default;
}
}
客户端配置:正向代理
以上,服务器的反代做好了,这时候如果把前后端都放上去,也就可以运行了。但又有另一个问题,我们在本地开发时,通常前端是跑在本地的,如localhost:8080。若要与后端交互,不又产生了跨域问题吗?
实际上,前人们肯定想到了这个问题,以Vue为例,在其配置中,我们很容易就可以写好代理来对请求做代理:
devServer: {
proxy: { // 代理
'/api': {
ws: false,
target: '后端所在的地址',
changeOrigin: true,
secure: false,
}
}
}
这样,在请求localhost:8080/api/xxx的时候,本地服务器就会自动将请求转发到目标地址,这样,跨域问题就完美解决了!