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

  • 作者简介:大家好,我是文艺理科生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的方式解决跨域问题,并分别用代码举例进行了说明。

日拱一卒,功不唐捐。

相关推荐
神之王楠10 分钟前
如何通过js加载css和html
javascript·css·html
余生H15 分钟前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍18 分钟前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai22 分钟前
网站开发的发展(后端路由/前后端分离/前端路由)
前端
流烟默34 分钟前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
2401_857297911 小时前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
茶卡盐佑星_1 小时前
meta标签作用/SEO优化
前端·javascript·html
与衫1 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
Ink1 小时前
从底层看 path.resolve 实现
前端·node.js
金灰1 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5