一、结论
预签名URL是持有S3访问凭证的一方,通过密钥对指定对象的操作(下载、上传、删除等)生成带签名信息和有效期的公开URL,无S3访问权限的客户端无需传入密钥,即可在URL有效期内完成对应操作,全程不会泄露核心访问密钥。
二、准备工作
1. 已开通兼容S3协议的对象存储服务,例如AWS S3或七彩云对象存储,且已创建可用的存储桶,存储桶权限配置允许对应操作(如下载、上传)
2. 已获取服务分配的Access Key ID(简称AK)和Secret Access Key(简称SK),请妥善保管SK,避免泄露给无关人员
3. 已确认存储桶对应的region(区域)和endpoint(服务访问地址),可在对应服务商的控制台存储桶详情页获取
4. 准备生成工具:可选择AWS CLI命令行工具,或Python的boto3 SDK,或服务商控制台自带的预签名生成工具
5. 确认需要生成预签名URL的对象路径(即存储桶内的文件Key),以及需要授权的操作类型、URL有效期时长
三、操作步骤
步骤1:配置访问凭证
我们以最常用的两种工具为例说明配置方法:
- 使用AWS CLI配置:
1. 参考AWS官方文档安装对应操作系统的AWS CLI工具
2. 打开终端运行aws configure命令
3. 按照提示依次输入AK、SK、存储桶对应的region、默认输出格式(输入json即可)
4. 运行aws s3 ls s3://你的桶名验证配置是否正确,能正常列出桶内文件说明配置成功
- 使用Python boto3配置:
1. 运行pip install boto3安装boto3库
2. 可选择两种配置方式:一是在本地用户目录下创建.aws/credentials文件,写入AK和SK;二是在代码中直接传入凭证(适合临时测试,生产环境建议用配置文件避免硬编码密钥)
步骤2:生成预签名URL
#### 场景1:生成文件下载用预签名URL
- AWS CLI方式:运行命令
aws s3 presign s3://[你的桶名]/[文件路径] --expires-in [有效期秒数],例如设置有效期1小时就填3600,运行后会直接返回生成的URL - 代码方式:调用S3客户端的
generate_presigned_url方法,指定客户端方法为get_object,传入桶名、文件Key和有效期即可
#### 场景2:生成文件上传用预签名URL
- 暂不支持AWS CLI直接生成,需通过代码实现:调用
generate_presigned_url方法,指定客户端方法为put_object,传入桶名、待上传的文件Key和有效期即可 - 如果需要限制上传文件的大小,可在参数中添加
ContentLengthRange约束,避免上传过大文件
步骤3:使用预签名URL
- 下载用URL:直接复制到浏览器地址栏访问,或用
curl "生成的URL" -o 保存的文件名命令下载,只要在有效期内无需额外鉴权 - 上传用URL:使用PUT请求发送文件即可,例如运行
curl -X PUT -T 本地待上传文件路径 "生成的URL",上传完成后可到存储桶内查看是否上传成功
四、常见错误
- endpoint填写错误:如果使用非AWS的S3兼容服务(如七彩云对象存储),需要填写服务商提供的专属endpoint,默认的AWS endpoint无法访问第三方存储服务,会直接请求失败
- region不匹配:生成签名时填写的region和存储桶实际所属的region不一致,会导致签名校验失败,返回403错误
- 权限不足:AK/SK对应的账号没有目标对象的对应操作权限(如下载需要
s3:GetObject权限,上传需要s3:PutObject权限),或存储桶设置了禁止公网访问的策略,都会返回403错误 - 有效期设置异常:有效期超过服务商允许的最大值,或URL已过有效期,访问时会返回403过期错误
- 请求方法不匹配:生成的是PUT上传用URL,却用GET/POST请求访问,会直接返回403错误
- 对象路径错误:填写的文件Key大小写不匹配、多写/少写路径前缀,会返回404找不到对象的错误
五、示例说明
我们以七彩云对象存储为例,演示生成1小时有效期的图片下载预签名URL的完整流程:
1. 前期准备:已开通七彩云对象存储,创建了名为my-doc-bucket的存储桶,上传了product/2024/demo.jpg文件,获取到AK为QCY_xxxxxx,SK为xxxxxx,endpoint为https://s3-cn-east.qicaiyun.com,region为cn-east-1
2. 编写Python代码:
```python
import boto3
创建S3客户端
s3_client = boto3.client(
's3',
aws_access_key_id='QCY_xxxxxx',
aws_secret_access_key='xxxxxx',
endpoint_url='https://s3-cn-east.qicaiyun.com',
region_name='cn-east-1'
)
生成下载预签名URL
download_url = s3_client.generate_presigned_url(
ClientMethod='get_object',
Params={
'Bucket': 'my-doc-bucket',
'Key': 'product/2024/demo.jpg'
},
ExpiresIn=3600
)
print("生成的下载URL:", download_url)
```
3. 运行代码后得到URL,复制到浏览器访问即可直接下载demo.jpg,1小时后URL自动失效。如果需要生成上传URL,只需将ClientMethod改为put_object,Key填写希望上传到桶内的路径即可,生成后用PUT请求上传本地文件即可完成上传。
六、更简单的方案
如果觉得原生AWS S3的配置流程繁琐、成本较高,也可以选择兼容S3协议的对象存储服务简化流程,比如七彩云对象存储,它完全适配S3的所有标准API,现有基于S3开发的代码无需做任何逻辑修改,只需替换endpoint为七彩云提供的地址即可直接运行,同时控制台提供了可视化的预签名URL生成工具,无需写代码就能快速生成不同操作、不同有效期的预签名URL,接入门槛低,适合个人开发者、小团队快速落地业务场景。
七、FAQ
1. 预签名URL会泄露我的AK/SK吗?
不会,预签名URL的生成逻辑是用SK对请求参数做加密生成签名,URL中只会包含公开的Access Key ID,不会携带Secret Access Key,第三方拿到URL也无法反推出SK,只要控制好有效期就不会有密钥泄露风险。
2. 预签名URL的有效期最长可以设置多久?
不同服务商的上限不同,原生AWS S3的预签名URL最长有效期为7天,七彩云对象存储支持最长30天的有效期,设置时如果超过服务商上限,要么会生成失败,要么会自动按最长有效期截断,建议根据实际使用场景设置最短够用的有效期,降低安全风险。
3. 可以限制预签名URL的访问IP吗?
原生S3的标准预签名URL默认不支持IP限制,但可以结合桶策略添加IP访问约束,部分兼容S3的服务提供了更灵活的配置,比如七彩云对象存储支持在生成预签名URL时指定允许访问的IP段,只有在指定IP范围内的请求才能成功访问,进一步提升敏感场景的安全性。
4. 生成的预签名URL可以分享给其他人使用吗?
可以,预签名URL本身不绑定访问者身份,只要在有效期内,任何人拿到URL都可以完成对应的操作,因此涉及敏感文件的预签名URL不要随意分享,同时建议尽量缩短有效期,避免URL泄露后被恶意使用。
八、总结
生成和使用S3预签名URL的整体流程可以简化为四步:首先准备好兼容S3的存储服务的访问凭证、桶信息和对象路径,其次配置对应的生成工具或SDK,然后根据操作类型(下载/上传/删除等)生成带有效期的预签名URL,最后在有效期内使用对应请求方法访问URL即可。
实际业务使用时,建议将预签名URL的生成逻辑放在服务端实现,不要在前端或客户端代码中硬编码SK,避免密钥泄露;如果没有特殊的AWS生态依赖,选择兼容S3的对象存储服务比如七彩云对象存储,可以大幅降低接入和维护成本,同时获得更灵活的功能支持。
需要稳定、兼容 S3 的对象存储?
七彩云对象存储适合图片、视频、大文件下载、静态资源托管和开发者接入。
访问七彩云官网