2024 桐庐半程马拉松
00:00:00
时间
0.00
距离(公里)
--:--
配速
--
步频
--
心率 (bpm)
--
配速
步频
|
share-image
ESC

阿里云 OSS 跨域 (CORS) 问题排查与解决指南

在开发基于 Web 的应用时,我们经常会遇到前端 JavaScript 代码无法读取存储在阿里云 OSS(Object Storage Service)上的资源的问题。本文将详细记录一次典型的 CORS(跨域资源共享)问题的排查过程及解决方案。

问题描述

场景
我们编写了一个 Node.js 脚本抓取数据并上传到阿里云 OSS。然后,我们在 Hexo 博客的前端页面中使用 JavaScript (fetchXMLHttpRequest) 去请求这个 JSON 数据文件,以便渲染图表或列表。

现象

  1. 直接访问正常:将文件的 OSS URL 粘贴到浏览器地址栏,可以正常下载或预览文件,HTTP 状态码为 200。
  2. 代码请求失败:当网页代码尝试读取该文件时,浏览器控制台(Console)报错,通常显示 “Network Error” 或 “Failed to fetch”。
  3. 开发者工具查看:在 Network 面板中,请求状态可能显示为 (failed) 或 CORS error,无法查看 Response Data。

问题分析

这是一个经典的 跨域(Cross-Origin Resource Sharing, CORS) 问题。

什么是跨域?

浏览器的 同源策略(Same-Origin Policy) 是一项安全机制,它限制了从一个源(协议 + 域名 + 端口)加载的文档或脚本如何与来自另一个源的资源进行交互。

当您的博客(例如 https://wenjun.me)尝试去请求阿里云 OSS 的资源(例如 https://bucket-name.oss-cn-shanghai.aliyuncs.com/data.json)时,由于域名不同,浏览器会发起跨域请求。

为什么直接访问可以?

当您直接在浏览器地址栏输入 URL 时,这是一个“导航”行为,不受同源策略限制。但当您在 JS 代码中使用 fetchaxios 发起请求时,浏览器会严格检查服务器返回的响应头。

验证方法

我们可以使用 curl 命令来模拟请求并查看响应头:

curl -I -H "Origin: https://wenjun.me" https://your-bucket.oss-region.aliyuncs.com/your-file.json

如果响应头中 缺失 Access-Control-Allow-Origin 字段,那么浏览器就会拦截这次请求的响应数据,报跨域错误。

解决方案

要解决这个问题,我们需要在服务端(阿里云 OSS)配置允许跨域访问。

步骤一:登录阿里云 OSS 控制台

  1. 登录 阿里云 OSS 管理控制台
  2. 在左侧导航栏找到并点击您的 Bucket 名称(例如 file201503)。

步骤二:配置跨域规则

  1. 进入 数据安全 -> 跨域设置 (CORS)

  2. 点击 创建规则

  3. 按如下配置填写:

    • 来源 (Allowed Origins)

      • 建议填写您的网站域名,例如 https://wenjun.me
      • 如果用于测试,可以填 *(允许所有域名访问,但在生产环境建议限制域名)。
    • 允许 Methods (Allowed Methods)

      • 勾选 GET(如果只是读取文件)。
      • 如果有上传需求,可能需要勾选 PUT, POST 等。
    • 允许 Headers (Allowed Headers)

      • 填写 *(允许所有请求头)。
    • 暴露 Headers (Expose Headers)

      • 填写 ETag
      • 这允许前端 JS 代码访问 ETag 响应头,有时候缓存验证需要用到。
  4. 点击 确定 保存。

配置生效通常是秒级的。配置完成后,再次刷新您的网页,数据应该就能正常加载了。

进阶优化:设置正确的文件元数据

除了解决跨域问题,为了让文件在浏览器中体验更好,建议在上传时设置正确的文件头:

  1. Content-Type: 设置为 application/json(对于 JSON 文件)。这样浏览器知道它是一个数据文件而不是普通文本。
  2. Content-Disposition: 设置为 inline
    • inline:浏览器会尝试在窗口内直接预览内容。
    • attachment:浏览器会强制弹出下载框。

在 Node.js (ali-oss SDK) 中的代码示例:

const headers = {
// 指定存储类型
'x-oss-storage-class': 'Standard',
// 指定访问权限为公共读
'x-oss-object-acl': 'public-read',
// 设置为 inline 以便浏览器直接预览,而不是强制下载
'Content-Disposition': `inline; filename="${fileName}"`,
// 明确指定内容类型,避免浏览器误判
'Content-Type': 'application/json',
// 允许覆盖
'x-oss-forbid-overwrite': 'false',
};

await client.put(fileName, filePath, { headers });

通过以上配置,您可以完美解决前端从阿里云 OSS 读取数据的跨域问题,并优化用户体验。

文章作者:阿文
文章链接: https://www.awen.me/post/8a1f38da.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿文的博客