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

目录

  • 背景概述
  • 实现中遇到的问题
  • 解决
    • 方法1 - 反向代理
    • 方法2 - JSONP
      • 实现1
      • 实现2 借助jQuery(我用的)
    • 方法3 - 原生请求
    • 方法4 - 接口请求时请求头解决跨域

背景概述

开发过程中对接读卡器硬件时,和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'
  })
}

调用接口 出现跨域问题

GetCardNum() {
  GetCardNum().then((res) => {
    this.$set(this.formData, 'rfid', res.cardnum || '')
  })
}

解决

方法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: {
    // ...
  }
}

方法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)

实现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 数据即为接口返回的读取读卡器数据
    }
  })
})

方法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) // 处理错误信息
  })


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({
    // 请求体数据,如果不需要发送请求体,则可以省略该部分
    // 根据你的接口定义,替换成对应的请求体数据
  })
)

方法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']
  )
}

你可能感兴趣的:(项目问题,对接硬件,前端)