You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS预签名URL初始访问报403错误,等待15秒后恢复正常

问题:AWS S3预签名URL在浏览器中延迟可用,Postman可立即访问

我在后端用以下代码生成AWS S3存储桶中MP3文件的预签名URL:

const s3Client = new S3Client({
    credentials: {
        accessKeyId: "AAAAAAAAAAAAAAAAAAAA",
        secretAccessKey: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
    }
});

const getObjectCommand = new GetObjectCommand({
    Bucket: "my-bucket-name",
    Key: "file-to-be-used"
});

// 生成GET请求的预签名URL
const url = await getSignedUrl(s3Client, getObjectCommand, { expiresIn: 300 }).then(data => {
    ...
    做一些处理后返回URL
    ...
});

Postman表现

调用后端接口获取预签名URL后,在Postman中可立即正常访问(直接点击即可打开)。

浏览器表现

但在浏览器中使用该URL时(比如设为HTMLAudioElement的源,或通过fetch请求访问),会出现403 - Access forbidden错误。

异常细节

等待约15秒后再访问同一个URL,就能正常使用了——直接点击可在浏览器打开,设为音频元素源也能正常播放。

操作过程显示:获取URL后,两次尝试访问(一次设为音频源、一次fetch请求)都返回403;初始两次在新标签页打开URL也报403,第三次点击(或等待15秒后)则恢复正常。

  • 无任何CORS相关错误(已配置CORS,AllowedHeaders和AllowedOrigins均设为*)
  • Postman和浏览器用的是同一个后端生成的完全相同的URL

更新

按建议改用us-east-1标准区域的存储桶,问题依旧。

Postman中的请求及请求头

请求URL:

https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIASAQ3L4XYIZI4YD73%2F20230311%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230311T220846Z&X-Amz-Expires=300&X-Amz-Signature=b3c081018ea7e9f7979a65267f66bfdcf2f185d2f824bd86fa9ae9141e8ba627&X-Amz-SignedHeaders=host&x-id=GetObject

拆分后:

https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&
X-Amz-Credential=AKIASAQ3L4XYIZI4YD73%2F20230311%2Fus-east-1%2Fs3%2Faws4_request&
X-Amz-Date=20230311T220846Z&
X-Amz-Expires=300&
X-Amz-Signature=b3c081018ea7e9f7979a65267f66bfdcf2f185d2f824bd86fa9ae9141e8ba627&
X-Amz-SignedHeaders=host&
x-id=GetObject

请求头:

User-Agent: PostmanRuntime/7.31.1
Accept: */*
Postman-Token: 4364aac9-1334-4434-b9a9-0b792dbde7b5
Host: presigned-url-test-tim.s3.us-east-1.amazonaws.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

浏览器中的请求及请求头

请求URL:

https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIASAQ3L4XYIZI4YD73/20230311/us-east-1/s3/aws4_request&X-Amz-Date=20230311T220557Z&X-Amz-Expires=300&X-Amz-Signature=e58bdbb1af3d4d47e1ec7c2aeaab3f77dd3a1fd7987831f1d0e6367a359637ef&X-Amz-SignedHeaders=host&x-id=GetObject

拆分后:

https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&
X-Amz-Credential=AKIASAQ3L4XYIZI4YD73/20230311/us-east-1/s3/aws4_request&
X-Amz-Date=20230311T220557Z&
X-Amz-Expires=300&
X-Amz-Signature=e58bdbb1af3d4d47e1ec7c2aeaab3f77dd3a1fd7987831f1d0e6367a359637ef&
X-Amz-SignedHeaders=host&
x-id=GetObject

可能的原因及解决方案

1. 后端与S3的时间同步偏差

AWS签名机制依赖精确的X-Amz-Date时间戳,若后端服务器时间与AWS服务器时间差超过5分钟,会直接导致签名验证失败。等待15秒后时间偏差缩小到允许范围内,URL就会生效。

解决方法:

  • 开启后端服务器的NTP服务,同步标准UTC时间。
  • 检查服务器时间与UTC的差值,确保控制在5分钟以内。

2. URL编码不一致问题

对比Postman和浏览器的请求URL,X-Amz-Credential参数中的斜杠在Postman中是URL编码后的%2F,但浏览器中是原始的/。虽然多数场景下浏览器会自动处理,但部分情况会触发签名验证失败。

解决方法:

  • 后端生成预签名URL后,对特殊字符(如斜杠)做URL编码再返回给前端。
  • 前端接收URL后,用encodeURI()对整个URL编码后再使用。

3. S3最终一致性延迟

如果MP3文件是刚上传就生成预签名URL,S3的最终一致性模型会导致短时间内对象未完成同步,返回403。等待15秒后对象同步完成,即可正常访问。

解决方法:

  • 若文件是刚上传的,延迟几秒再生成预签名URL。
  • 开启S3版本控制,生成URL时携带VersionId参数;或通过PUT操作返回的ETag确认对象写入完成后再生成URL。

4. 浏览器预加载机制干扰

浏览器可能会在URL返回后立即发起预请求(比如音频元素的自动预加载),此时签名因时间偏差等原因未生效,导致403。等待后重新请求时条件满足即可访问。

解决方法:

  • 对HTMLAudioElement设置preload="none",需要播放时再手动设置src并调用load()。
  • 手动控制请求时机,避免浏览器自动预请求。

内容的提问来源于stack exchange,提问作者Gorgsenegger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:27:02