如何限制S3存储桶仅允许上传预签名URL指定文件名的文件
S3预签名URL限制仅上传指定文件名的实现方案
核心原理
S3预签名URL的签名计算会包含对象Key(也就是存储在S3中的文件名/路径)、请求方法、指定请求头等核心参数,任意修改这些参数都会导致签名校验失败,S3会直接返回403错误拒绝请求,无需额外开发拦截逻辑。
1. PHP后端生成预签名URL时固定对象Key
你只需要在生成预签名URL的阶段,将S3对象的Key参数写死为允许上传的文件名(比如示例中的stack.txt),完全不要把Key的控制权交给前端即可。
以下是AWS SDK for PHP的实现示例:
<?php require 'vendor/autoload.php'; use Aws\S3\S3Client; $s3Client = new S3Client([ 'version' => 'latest', 'region' => '你的S3区域码,比如ap-beijing', 'credentials' => [ 'key' => '你的AWS访问密钥ID', 'secret' => '你的AWS秘密访问密钥', ] ]); // 固定允许上传的文件名,禁止从前端传参获取该值 $allowedFileName = 'stack.txt'; $bucketName = '你的S3存储桶名称'; // 构造PutObject命令,所有参数固定 $command = $s3Client->getCommand('PutObject', [ 'Bucket' => $bucketName, 'Key' => $allowedFileName, // 可选:固定ContentType,进一步限制上传文件类型 'ContentType' => 'text/plain', ]); // 生成有效期为10分钟的预签名URL $presignedRequest = $s3Client->createPresignedRequest($command, '+10 minutes'); $presignedUrl = (string) $presignedRequest->getUri(); // 直接将该URL返回给前端即可
2. 额外安全加固(可选)
如果需要再加一层兜底限制,可以配置S3存储桶策略,禁止所有上传非指定文件名的请求:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::你的存储桶名称/*", "Condition": { "StringNotEquals": { "s3:key": "stack.txt" } } } ] }
3. 前端使用要求
前端拿到预签名URL后,直接发起PUT请求上传文件二进制内容即可,不要修改URL的任何参数,也不要自行拼接上传路径,修改URL的任意部分都会直接触发S3的签名校验失败。
内容的提问来源于stack exchange,提问作者Avinash Pratap Singh
相关产品推荐
相关产品推荐

