如何授权Cognito用户访问AWS静态S3存储桶的私有内容?
S3静态网站权限问题排查结论
现有IAM策略的错误
你写的策略存在多处语法和逻辑错误,根本无法按预期生效:
- 资源ARN配置错误:
s3:GetObject属于对象级操作,要求资源ARN必须精确到对象路径,你当前填写的arn:aws:s3:::mybucket(桶级ARN)、arn:aws:s3:::mybucket/user(前缀级ARN)都不符合要求,所有GetObject请求都无法匹配到允许规则,会被默认拒绝。 - 条件键使用场景错误:
s3:prefix、s3:delimiter这两个条件键仅对ListBucket这类列举桶内容的桶级操作生效,在GetObject对象读取请求中不会触发校验,你加的这部分条件完全无效。 - Cognito上下文键用错:
${aws:username}仅对IAM用户、IAM用户签发的临时凭证生效,Cognito用户池认证后的请求不会携带这个字段,Cognito用户的用户名对应的上下文键是${cognito:username},用错键会导致永远无法匹配到用户专属目录。 - 逻辑遗漏:你期望放开根目录访问,但静态网站默认访问的是根目录下的
index.html等具体文件,原策略仅匹配空前缀,根本不会命中实际的页面对象。
开启「阻止所有公有访问」时的策略生效规则
这个配置的优先级高于所有IAM策略、桶策略,能不能生效要看你的访问模式:
- 如果你期望根目录、public目录支持匿名无签名访问,开着全量Block Public Access时策略完全无法生效,服务端会直接拦截所有匿名请求。
- 如果你通过CloudFront+OAC源访问控制回源S3、或者所有请求都携带Cognito兑换的合法签名临时凭证,Block Public Access不会拦截这类请求,策略可以正常生效,这种模式也是AWS推荐的安全架构,不需要开放S3的公网匿名访问。
- 如果你坚持直接用S3原生静态网站端点提供匿名访问,需要手动关闭Block Public Access中「阻止通过新公共桶策略授予的桶和对象公有访问权」「阻止通过任意公共桶策略授予的桶和对象公有/跨账号访问权」两个开关,剩下的ACL相关阻止开关可以保持开启。
修复方案与后续排查方向
- 先补全Cognito链路:仅靠Cognito用户池签发的JWT无法直接访问S3,必须将用户池和Cognito身份池联邦,通过用户池JWT兑换身份池的临时AWS凭证,用该凭证对S3请求做签名才能被S3识别,这是绝大多数人卡Cognito+S3权限链路的核心原因。
- 替换错误的策略:如果策略是绑定给Cognito认证用户对应的IAM角色,可参考如下修正版本:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessToPublicResources", "Effect": "Allow", "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::mybucket/public/*", "arn:aws:s3:::mybucket/index.html", "arn:aws:s3:::mybucket/error.html" ] }, { "Sid": "AllowAccessToOwnUserDirectory", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::mybucket/user/${cognito:username}/*" } ] }
- 排查顺序建议:先通过AWS CLI使用兑换到的临时凭证测试S3对象读取权限,确认IAM链路完全打通后,再调试前端静态网站的访问逻辑,不要一开始就从浏览器端排错,避免缓存、CORS等无关问题干扰判断。
- 权限边界检查:确认Cognito身份池绑定的IAM角色没有配置权限边界,同时账号层面没有SCP组织策略显式拒绝对对应S3桶的访问。
内容的提问来源于stack exchange,提问作者sschlegelmilch
相关产品推荐
相关产品推荐

