打破壁垒:前端跨域问题的优雅解决方案

  • 作者简介:大家好,我是文艺理科生Owen,某车企前端开发,负责AIGC+RAG项目
  • 目前在卷的技术方向:工程化系列,主要偏向最佳实践
  • 希望可以在评论区交流互动,感谢支持~~~

有一天,忘记带电脑回家,公司临时通知加班,不得已只好拿女友的电脑将就。考虑到需要准备环境,所以先简单调试一下,第二天直接把代码贴上去就省事了。

vscode还是要安装的,总不能拿记事本手敲。。。

说干就干。

新建了一个html页面,请求一个接口,查看下接口返回的数据结构。

先用最简单的ajax吧,顺便也复习复习(随时做好面试的准备)

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <script>
      let xhr = new XMLHttpRequest()
      xhr.onreadystatechange = () => {
        if(xhr.readyState === 4) {
          if(xhr.status === 'OK') {
            console.log("🚀 ~ xhr.responseText:", xhr.responseText)
          } else {
            alert('request fail');
          }
        }
      }
      xhr.open('get', 'https://kaifa.baidu.com/rest/v1/recommend/hotwords?tabIndex=ALL')
      xhr.send(null)
    </script>
  </body>
</html>

其中接口地址脱敏处理,网上找了一个代替,在地址栏单独访问是成功的。

使用live server打开html文件,结果是失败的

可以看到报错提示:资源请求头中无 Access-Control-Allow-Origin,出现了跨域问题。

跨域安全策略是前端脚本代码向不同域名的服务器发起请求时遇到的同源策略限制,目的是防止某些恶意行为非法获取资源。不过,浏览器也支持合法跨域访问的能力。

对于简单的GET和POST请求,发送时会携带额外的Origin头部,包含发起请求方的源地址(协议、域名、端口号),如 Origin: http://127.0.0.1:5500,等待服务器确定是否响应。

若服务器决定响应请求,则会在响应头中携带Access-Control-Allow-Origin头部,包含请求方的源地址,或包含"*"(指资源完全公开)。如 Access-Control-Allow-Origin: http://127.0.0.1:5500

说了这么多,怎么解决呢?方法有很多种,当然先找一种最快最简单的。

浏览器插件解决跨域

在谷歌插件应用市场中,搜索 Allow CORS,下载安装。

切换到测试页面,打开刚才的插件,点击 Toggle ON,开启允许跨域。然后刷新页面。

跨域问题解决了,就这么快。

我们对比一下开启前和开启后的响应头信息:

可以清楚看出:开启后响应头增加了Access-Control-Allow-MethodsAccess-Control-Allow-Origin两个字段。最主要的是Access-Control-Allow-Origin:http://127.0.0.1:5500,意思是非同源中只有 http://127.0.0.1:5500能够正常请求到资源。

图片探测

通过img的src属性可以跨域加载图片而不受限制(前提是被请求的服务器正确设置了Access-Control-Allow-Origin)。代码如下:

ini 复制代码
<div id="box"></div>
<script>
  let img = new Image()
  img.onload = img.onerror = function () {
    console.log('完成请求了!')
  }
  img.crossOrigin = 'anonymous'
  img.src = 'https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/e08da34488b114bd4c665ba2fa520a31.svg'
  img.style.width = '100px'
  img.style.height = '100px'
  const box  = document.getElementById('box')
  box.append(img)
</script>

通过js创建Image实例,在实例上添加onload和onerror事件添加处理函数,当请求完成时可以收到通知。将img实例挂载到box元素下面进行渲染,展示正常。

图片探测主要用于跟踪用户的点击操作或动态显示广告。缺点是只能发送GET请求和只能完成向服务器的单向通信。

JSONP

类似于img图片探测,JSONP是通过动态创建script元素,将其src属性设置为跨域url实现的。

代码如下:

xml 复制代码
<script>
  function handleResponse(response) {
    console.log(response, 'response');
  }
  let script = document.createElement("script");
  script.src = "http://jsonplaceholder.typicode.com/posts?callback=handleResponse";
  document.body.insertBefore(script, document.body.firstChild);
</script>

控制台中可以获取到结果:

JSONP简单易用,相比于图片探测,可以实现浏览器与服务器的双向通信。缺点是获取可执行代码的域存在不安全风险。

总结:本文通过一个场景引出跨域出现的场景,并通过采用浏览器插件、图片探测和JSONP的方式解决跨域问题,并分别用代码举例进行了说明。

日拱一卒,功不唐捐。

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排5 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!7 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰7 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen9 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马10 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu10 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss