解决vue3+axios浏览器请求跨域问题-Access to XMLHttpRequest错误解决

947 阅读2分钟

vue3 + axios 跨域问题解决方案

1. 报错情况如下

控制台报错:Access to XMLHttpRequest at 'http://xxx' from origin 'http://xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. 出现原因

出于浏览器的同源策略限制,导致本地服务访问其他地址时,无法获取相应的数据,即为跨域

同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

当前页面url被请求页面url是否跨域原因
www.test.com/www.test.com/index.html同源(协议、域名、端口号相同)
www.test.com/www.test.com/index.html跨域协议不同(http/https)
www.test.com/www.baidu.com/跨域主域名不同(test/baidu)
www.test.com/blog.test.com/跨域子域名不同(www/blog)
www.test.com:8080/www.test.com:7001/跨域端口号不同(8080/7001)

3. 解决方案

丑话说在前头:该解决方案仅用于解决开发阶段拿不到数据的问题,上线后还是会遇到,所以根源还是得后端服务器对于CORS的支持,需要后端进行配置

3.1 axios请求与proxy代理配置

  1. 原理:浏览器通过webpack本地代理请求远程服务器
sequenceDiagram
本地服务器->>webpack代理服务器: 发送请求
webpack代理服务器->>目标服务器: 转发本地服务器请求
目标服务器-->>webpack代理服务器: 获取数据
webpack代理服务器-)本地服务器: 拿到数据
  1. proxy代理配置

    目标文件:vue.config.js

    //vue.config.js文件配置
    const { defineConfig } = require('@vue/cli-service')
    module.exports = defineConfig({
      transpileDependencies: true,
      lintOnSave: false,
    
      publicPath: './',
      devServer: {
        host: 'localhost', //自己的ip地址
        // https: true,
        port: 6103, //自己服务器的端口号
        // client: {
        //   webSocketURL: 'ws://0.0.0.0:6103/ws',
        // },
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
        proxy: {
            // '/interface' 可以理解为 请求目标地址的标识符,也可以使用其他命名代替
          '/interface': {
              target:'http://60.15.96.130:8092/interface',
              changeOrigin: true,       //是否跨域
              ws: true,            //是否代理 websockets
              secure: true,          //是否https接口
              pathRewrite: {
                '^/interface': ''//这里理解成用‘/interface’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用'http://40.00.100.100:3002/user/add',直接写‘/interface/user/add’即可   
              }
          }
        }
      },
    
    })
    
    
  2. 使用案例

    // 创建 供热 实例对象
    import axios from 'axios';
    
    export const heatingService = axios.create({
      baseURL: "/interface", //此处将通过webpack进行代理
      timeout: 30000, // 设置请求超时时间设置为30秒
      responseType: 'json',
      withCredentials: true, // 是否允许带cookie这些
    });
    
    getPrimaryPipeNet() {
        return heatingService({
            url: "getPrimaryPipeNet",
            method: 'get',
        })
    }
    
    async getHeadingPipe() {
      const data = await heatingApi.getPrimaryPipeNet();
      console.log("数据", data);
    },