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

如何用Python匿名访问带区域限制的AWS S3公开存储桶?

问题描述

我有一个AWS S3公开存储桶,桶策略仅允许来自us-west-1和us-west-2区域的访问。想通过boto3/s3fs在Python中匿名访问该桶并列出所有文件,无需凭证登录。

对应的桶策略片段:

{
    "Sid": "Statement2",
    "Effect": "Allow",
    "Principal": {
        "AWS": "*"
    },
    "Action": [
        "s3:GetObject",
        "s3:GetBucketLocation",
        "s3:ListBucket",
        "s3:GetBucketAcl"
    ],
    "Resource": [
        "arn:aws:s3:::MY-BUCKET",
        "arn:aws:s3:::MY-BUCKET/*"
    ],
    "Condition": {
        "StringEquals": {
            "aws:RequestedRegion": [
                "us-west-1",
                "us-west-2"
            ]
        }
    }
}

尝试过的代码:

import boto3
from botocore.config import Config
import botocore

s3_client = boto3.client('s3', region_name='us-west-2', config=Config(signature_version=botocore.UNSIGNED))
s3_client.list_objects(Bucket='MY-BUCKET')

运行后返回访问拒绝错误,但不指定请求区域时代码可以正常工作,需要解决这个配置问题。

解决思路与方案

原因分析

指定region_name时,boto3会直接向该区域的S3端点发送请求,但如果你的桶实际不在us-west-2区域,S3会因为aws:RequestedRegion不匹配桶的真实区域而拒绝请求。不指定区域时,boto3会先请求全局S3端点,自动重定向到桶的实际区域,此时aws:RequestedRegion匹配桶的真实区域,请求得以通过。


方案1:调整桶策略(推荐)

方式A:添加桶实际所在区域到允许列表

如果知道桶的实际区域(比如us-east-1),直接将其加入aws:RequestedRegion的允许列表:

"Condition": {
    "StringEquals": {
        "aws:RequestedRegion": [
            "us-west-1",
            "us-west-2",
            "us-east-1"  // 替换为你的桶实际区域
        ]
    }
}

方式B:改用客户端来源区域限制

如果要限制的是发起请求的客户端所在区域,将aws:RequestedRegion替换为aws:SourceRegion:

"Condition": {
    "StringEquals": {
        "aws:SourceRegion": [
            "us-west-1",
            "us-west-2"
        ]
    }
}

方案2:修改boto3代码,动态获取桶区域

先匿名获取桶的实际区域,再用该区域创建客户端发起请求:

import boto3
from botocore.config import Config
import botocore

# 匿名获取桶的实际区域
s3_client_no_region = boto3.client('s3', config=Config(signature_version=botocore.UNSIGNED))
bucket_region = s3_client_no_region.get_bucket_location(Bucket='MY-BUCKET')['LocationConstraint']
# 处理us-east-1的特殊情况(get_bucket_location返回None)
if not bucket_region:
    bucket_region = 'us-east-1'

# 使用桶实际区域创建客户端并列出文件
s3_client = boto3.client('s3', region_name=bucket_region, config=Config(signature_version=botocore.UNSIGNED))
response = s3_client.list_objects(Bucket='MY-BUCKET')

# 遍历输出文件
for obj in response.get('Contents', []):
    print(obj['Key'])

方案3:使用s3fs简化实现

s3fs默认会自动处理区域重定向,无需手动指定区域,直接匿名初始化即可:

import s3fs

# 匿名创建文件系统实例
fs = s3fs.S3FileSystem(anon=True)

# 列出桶内所有文件
files = fs.ls('MY-BUCKET')
print(files)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:37:04