AWS S3未配置CORS策略,为何Amplify Storage.get可正常获取对象URL而Storage.list返回403?
这是个非常典型的Amplify Storage使用困惑,核心原因在于Storage.get和Storage.list的底层实现逻辑完全不同,导致它们对S3 CORS策略的依赖不一样:
1. Storage.get的工作逻辑(为什么没触发CORS错误)
当你调用带expires参数的Storage.get(针对private级别的文件)时,Amplify的行为是:
- 利用你前端的AWS身份凭证(通常来自Cognito用户池/身份池)在本地生成一个预签名URL,这个过程不需要向S3发起任何跨域API请求。
- 返回的预签名URL本身是一个直接指向S3对象的临时可访问链接,当你用这个URL访问文件时:
- 如果是通过
<img>、<script>等嵌入标签加载资源,浏览器不会触发CORS检查(这类请求属于“嵌入资源请求”,不受CORS策略限制),所以你能正常看到图片。 - 如果你用
fetch或XMLHttpRequest去请求这个URL,此时浏览器会触发CORS检查,因为S3桶没有配置CORS策略,你会收到预期的403 CORS错误。
- 如果是通过
你看到的“无错误返回有效URL”,本质是Storage.get方法本身没有发起跨域请求,它只是完成了预签名URL的本地生成,自然不会触发CORS拦截。
2. Storage.list的工作逻辑(为什么符合预期返回403)
Storage.list方法的底层是直接调用S3的ListObjectsV2 API,这个请求是通过前端的fetch/XMLHttpRequest发送的跨域请求:
- 浏览器会先发送OPTIONS预检请求(因为ListObjects属于非简单请求),检查S3是否允许当前源的跨域访问。
- 由于你的S3桶没有配置CORS策略,S3不会返回
Access-Control-Allow-Origin等必要头,浏览器直接拦截请求并返回403 Forbidden的CORS错误,这和你的预期一致。
如何让CORS策略适用于Storage.get的场景?
如果你希望即使用预签名URL访问文件时也受CORS策略限制(比如防止其他网站通过预签名URL加载你的私有文件),或者希望在Storage.get的流程中也强制检查CORS,你需要做以下配置:
配置S3桶的CORS策略
首先为S3桶添加CORS策略,允许你的前端源访问,例如:
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET", "HEAD"], "AllowedOrigins": ["https://your-amplify-app-url.com"], "ExposeHeaders": [] } ]
这样当你用fetch/XMLHttpRequest请求预签名URL时,S3会返回正确的CORS头,而如果请求源不在AllowedOrigins列表中,就会触发CORS错误。
强制Storage.get通过Amplify后端代理请求(可选)
如果你希望Storage.get的过程也必须经过Amplify的后端(从而可以在后端添加额外的权限控制,同时让请求受CORS策略限制),可以修改Amplify Storage的配置,启用代理模式:
Amplify.configure({ Storage: { S3: { bucket: 'your-bucket-name', region: 'your-region', proxy: true // 启用代理,让请求通过Amplify后端转发 } } });
启用代理后,Storage.get会向Amplify的后端API发起请求,再由后端去S3获取预签名URL或直接返回文件内容,此时这个请求会受Amplify后端的CORS配置限制,你可以在Amplify控制台配置后端的CORS规则。
内容的提问来源于stack exchange,提问作者Kevin

