• 前端解决跨域 3 种方法 -对接读卡器时出现跨域问题


    背景概述

    开发过程中对接读卡器硬件时,和C++工程师对接,C++工程师写了一个程序,安装到自己电脑上后会提供一个接口 http://localhost:5001/api/XXXXX 用来获取读卡器读取到的数据(该数据是经过C++程序处理过的)

    具体过程:

    1. 安装C++程序到本机
    2. 将磁卡放在读卡器上(读卡器插在自己电脑上)
    3. 调用接口 http://localhost:5001/api/XXXXX

    实现中遇到的问题

    • 我们自己本地运行项目时,使用【方法1】反向代理可以;
    • 项目部署到线上时,我们前端写的反向代理是不会打包进包里的,需要后端 nginx 配置代理,但是后端 nginx 代理如果代理地址写 http://localhost:5001 只能代理到服务器,而不能代理到我们本机(C++的程序是在我们自己电脑安装的,服务器访问不到)
    • 而我们线上如果直接请求地址 http://localhost:5001/api/XXXXX ,会有跨域问题
    • 【所以】我们需要解决一下跨域:使用【方法2】【方法3】

    api.js 文件中封装接口

    export function XXX() {
      return request({
        url: '/RFID/api/XXX'
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    调用接口 出现跨域问题

    GetCardNum() {
      GetCardNum().then((res) => {
        this.$set(this.formData, 'rfid', res.cardnum || '')
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解决

    方法1 - 反向代理

    vue.config.js 文件中 将以 /RFID 开头的地址代理到本地程序地址即可

    module.exports = {
      // ...
      // webpack-dev-server 相关配置
      devServer: {
        host: '0.0.0.0',
        port: 8080,
        https: false,
        hotOnly: false,
        open: true, // 自动打开浏览器
        proxy: {
          // ...
          '^/RFID': {
            target: 'http://localhost:5001', // 【主要代码】
            pathRewrite: { '^/RFID': '' }
          },
          '/': {
            target: 'http://192.168.0.42:9000'
          }
        }
      },
      // 第三方插件配置
      pluginOptions: {
        // ...
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    方法2 - JSONP

    需要 C++ 工程师配合一下,需要调用一下 url 的 查询参数 callback

    实现1

    // 提供jsonp服务的url地址;
    var url = 'http://localhost:5001/api/GetCardNum'
    // 创建script标签,设置其属性;
    var script = document.createElement('script')
    script.setAttribute('src', url)
    document.getElementsByTagName('head')[0].appendChild(script)
    // 得到查询结果后的回调函数;
    var callback = (data) => {
      var json = JSON.stringify(data)
      console.log('json----', json)
    }
    callback(132465)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实现2 借助jQuery(我用的)

    借助jQuery

    import $ from 'jquery'
    
    
    const that = this
    $(function () {
      // 发起JSONP的请求
      $.ajax({
        url: 'http://localhost:5001/api/XXX',
        // 代表我们要发起JSONP的数据请求
        dataType: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'fileCabinetHandler',
        success(res) {
          // res 数据即为接口返回的读取读卡器数据
        }
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    在这里插入图片描述

    方法3 - 原生请求

    var xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && [200, '200'].includes(xhr.status)) {
        console.log('xhr.responseText----', xhr.responseText)
      }
    }
    xhr.open('get', 'http://localhost:5001/api/GetCardNum', true)
    xhr.setRequestHeader('Content-Type', 'application/json')
    xhr.setRequestHeader('Access-Control-Allow-Origin', '*')
    xhr.send(null)
    
    jsonpRequest('http://localhost:5001/api/GetCardNum', null)
      .then((response) => {
        console.log(response) // 处理返回的数据
      })
      .catch((error) => {
        console.error(error) // 处理错误信息
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    
    
    var xhr = new XMLHttpRequest()
    // xhr.open('get', 'http://192.168.10.106:5001/api/GetCardNum', true)
    xhr.open('get', 'http://127.0.0.1:5001/api/GetCardNum2', true)
    xhr.setRequestHeader('Content-Type', 'application/json') // 设置请求头中的 Content-Type
    xhr.setRequestHeader('Access-Control-Allow-Origin', '*') // 添加允许跨域的请求头
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          var data = JSON.parse(xhr.responseText)
          console.log('data----', data)
          // 处理响应数据
        } else {
          // 处理错误
        }
      }
    }
    xhr.send(
      JSON.stringify({
        // 请求体数据,如果不需要发送请求体,则可以省略该部分
        // 根据你的接口定义,替换成对应的请求体数据
      })
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    方法4 - 接口请求时请求头解决跨域

    // 接口请求头添加 Access-Control-Allow-Origin 为 * 解决跨域
    if (config.url === '/RFID/api/GetCardNum') {
    if (config.url === 'http://localhost:5001/api/GetCardNum') {
      config.url = 'http://localhost:5001/api/GetCardNum'
      // config.url = 'http://127.0.0.1:5001/api/GetCardNum'
    
      config.headers['Content-Type'] = 'application/json'
      config.headers['Access-Control-Allow-Origin'] = '*'
    
      console.log(
        'config.headers["Access-Control-Allow-Origin"]----',
        config.headers['Access-Control-Allow-Origin']
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    字符串思维题练习 DAY5(CF1137 B , CF 733D , CF 1360 F)
    windows下一键安装JDK1.8
    程序编码风格要求
    C# 将音频PCM数据封装成wav文件
    NumPy矩阵对象介绍及方法
    Qt学习20 Qt 中的标准对话框(中)
    计算机毕业设计ssm+vue基本微信小程序的校园二手商城系统
    网络安全(黑客)自学
    Java基于微信小程序的校园订餐小程序的研究与实现,附源码
    通过 Docker Compose 本地启动 hadoop 集群
  • 原文地址:https://blog.csdn.net/m0_53562074/article/details/133177967