Vue+Strapi开发环境下解决浏览器跨域问题

浏览器跨域问题是指浏览器在执行前端 JavaScript 请求时,访问了不同源(协议、域名或端口不同)的资源。

浏览器跨域问题的成因是同源策略,这是一种安全机制,限制网页从一个源加载的脚本与来自不同源的资源进行交互。两个URL的源由协议(如http/https)、主机(域名)和端口组成,若其中任一不同,则被视为跨域。例如,http://example.com和https://example.com因协议不同会被视为跨域。同源策略旨在防止恶意攻击,如跨站请求伪造(CSRF),保护用户数据安全。

例如:

当前网页地址被访问网页地址跨域原因
https://example.comhttp://example.com协议不同
http://example.comhttp://example.com:8080端口不同
https://example.comhttps://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开发环境下的浏览器跨域问题解决了。

Avatar photo

Sebastian

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注