SpringBoot应用上传至私有S3存储桶 仅允许指定Web应用访问方案问询
问题核心现状
你当前的配置存在三个核心问题,导致任何人都可以直接访问S3对象URL:
- 存储桶策略直接允许所有主体调用
s3:GetObject接口,等于完全开放公开读权限 - CORS策略中GET请求允许了所有来源,没有限制跨站访问范围
- 未开启公共访问拦截,存在配置错误导致资源泄露的风险
可选实现方案
方案1:限制请求Referer(快速实现,适合低安全要求场景)
该方案可以直接拦截普通用户在浏览器直接输入URL的访问请求,配置简单:
- 替换你的存储桶策略为以下内容,将
https://www.your-web-app.com替换为你实际的Web应用域名:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowGetFromSpecificReferer", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::nameofthebucket/*", "Condition": { "StringLike": { "aws:Referer": [ "https://www.your-web-app.com/*", "https://your-web-app.com/*" ] } } } ] }
- 修改CORS策略,将GET请求的允许来源改为仅你的Web应用域名:
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "PUT", "POST", "DELETE" ], "AllowedOrigins": [ "http://www.example1.com" ], "ExposeHeaders": [] }, { "AllowedHeaders": [], "AllowedMethods": [ "GET" ], "AllowedOrigins": [ "https://www.your-web-app.com", "https://your-web-app.com" ], "ExposeHeaders": [] } ]
注意:该方案存在局限性,Referer请求头可以被人为伪造,无法防御刻意构造的非法访问请求。
方案2:签名URL/签名Cookie(生产环境推荐,安全性最高)
该方案从权限根源限制访问,只有你的Web应用可以生成合法的访问链接,原始S3对象URL直接访问会被拒绝:
- 删除原有允许公开读的存储桶策略,开启S3桶的「Block public access」全部四个拦截选项
- 给你的Web应用对应的IAM身份(服务器角色、应用服务账号等)授予
s3:GetObject权限 - 所有S3资源的访问链接由Web应用后端生成,调用AWS SDK生成带过期时间的签名URL,过期时间可根据业务需求设置(通常为几分钟到几小时),Python示例代码如下:
import boto3 from botocore.config import Config s3 = boto3.client('s3', config=Config(signature_version='s3v4')) signed_url = s3.generate_presigned_url( 'get_object', Params={'Bucket': 'nameofthebucket', 'Key': 'your-object-key'}, ExpiresIn=3600 # 签名有效期1小时,单位为秒 )
- 前端直接使用后端返回的签名URL访问资源即可,用户即使拿到原始S3对象URL也无法访问。
方案3:限制固定出口IP(适合Web应用有固定公网IP的场景)
如果你的Web应用部署在有固定公网出口IP的服务器上,可以直接在存储桶策略中限制仅该IP可以访问,策略示例如下,替换1.2.3.4/32为你实际的出口IP段:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowGetFromSpecificIP", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::nameofthebucket/*", "Condition": { "IpAddress": { "aws:SourceIp": "1.2.3.4/32" } } } ] }
注意事项
- 所有存储桶权限配置修改后可以先测试普通访问是否被拦截、应用内访问是否正常,避免影响业务
- 签名URL的生成逻辑必须放在后端实现,禁止在前端代码中硬编码S3访问密钥
- 有CDN加速需求的场景可以搭配CloudFront使用,通过CloudFront OAC访问S3,完全隐藏S3源站入口,进一步提升安全性
内容的提问来源于stack exchange,提问作者dassoop
相关产品推荐
相关产品推荐

