浏览器跨域问题是指浏览器在执行前端 JavaScript 请求时,访问了不同源(协议、域名或端口不同)的资源。
浏览器跨域问题的成因是同源策略,这是一种安全机制,限制网页从一个源加载的脚本与来自不同源的资源进行交互。两个URL的源由协议(如http/https)、主机(域名)和端口组成,若其中任一不同,则被视为跨域。例如,http://example.com和https://example.com因协议不同会被视为跨域。同源策略旨在防止恶意攻击,如跨站请求伪造(CSRF),保护用户数据安全。
例如:
当前网页地址 | 被访问网页地址 | 跨域原因 |
https://example.com | http://example.com | 协议不同 |
http://example.com | http://example.com:8080 | 端口不同 |
https://example.com | https://pan.example.com | 子域名不同 |
解决措施
现在,笔者以一个基于Vue和Strapi的Web服务为例,在调用后端的API接口时,常出现的浏览器跨域问题,提供一些解决措施。(服务器为腾讯云服务器,安装了宝塔面板,中间件采用nginx)
笔者将后端需要的数据写好后,访问部署好的前端页面时,发现本应出现数据的页面却是空白,随后通过Apifox/PostMan等工具,对写好的API接口进行测试,发现通过 Vue 前端通过域名(如 https://example.com)访问 Strapi 提供的 API 接口(如/api/test_info)时,返回空白页面
,但通过 IP + 端口
(如 http://服务器IP:1337/api/test_info
)访问则可以成功获取数据。
根据分析,既然能够通过IP加端口的方式访问到正确的API接口数据,那么说明我们的后端Strapi是正常工作的,那么问题如上表格所示,我们的当前页面是https://www.example.com,而对于API的请求是http://服务器IP:1337/api/test_info,显然,这构成了上述的浏览器跨域问题。
经过分析,我们可以发现,我们只需要将对于API的请求统一为域名/api/test_info的形式即可,那么我们来到nginx的网站根目录下,笔者的目录是”/www/server/nginx/conf”,我们找到对应域名的.conf配置文件,并对其做反向代理即可
server {
listen 443 ssl;
server_name your_domain;
ssl_certificate /www/server/panel/vhost/cert/your_domain/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/your_domain/privkey.pem;
# Vue 前端静态资源配置
location / {
root /your_path;
index index.html;
try_files $uri $uri/ /index.html;
}
# API 代理配置
location /api/ {
proxy_pass http://127.0.0.1:1337;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#uploads配置
location /uploads/ {
proxy_pass http://127.0.0.1:1337/uploads;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /var/log/nginx/your_domain_access.log;
error_log /var/log/nginx/your_domain_error.log;
}
注意:“proxy_pass http://127.0.0.1:1337;”中,1337后不需要再添加/,/的作用是省略/api/中第二个/,若添加/,实际拼接后得到API路由为127.0.0.1:1337api/test_info,显然该路由缺少分隔符/,直接访问会报404错误。
经过上述配置,从浏览器的视角来看,前端向后端请求的URL是:https://example.com/api/test_info,实际上我们通过nginx,将请求反向代理到了服务器的http://127.0.0.1:1337/api/test_info上,但对于浏览器而言,它看到的实际情况是,当前页面是https://example.com/,前端对后端请求是:https://example.com/api/test_info,我们巧妙地通过反向代理骗过了浏览器的检测,于是成功解决了浏览器跨域问题。
Tips
然而,当笔者将上述项目从A服务器迁移到B服务器后,发现了一个新问题,访问IP加端口/api时能够正常获取到数据,但是访问域名/api时,浏览器报错404 Not Found。这个问题困扰我许久,经过不懈努力,终于发现了解决方法。
对上述情况分析,我们知道问题还是出在了nginx上,但是配置文件已经做了反向代理了,为什么会抛出异常404呢?事实上,我前面提到过,笔者使用的是腾讯云服务器,已经安装了宝塔面板,但实际上,宝塔面板默认读取的nginx配置文件路径并非上述提到的”/www/server/nginx/conf”,而是“/www/server/panel/vhost/nginx”,您只需将两处配置文件同时修改,即可彻底解决问题。您可以通过:
nginx -T | grep 您的域名
查看关于您域名的所有配置nginx文件,找到默认使用的conf文件,并为其配置正确的反向代理即可。
至此,关于Vue+Strapi开发环境下的浏览器跨域问题解决了。