如何配置AWS S3策略允许指定文件夹特定后缀访问并拒绝其他路径
你的判断是对的,核心原因就是AWS IAM权限评估体系中显式Deny的优先级永远高于所有显式Allow,但你之前修改Deny语句Principal的操作没生效,本质是Deny语句的资源匹配范围写得有问题:
你写的Deny语句匹配资源是arn:aws:s3:::my-bucket/*,这个范围覆盖了存储桶下所有路径,自然也包含前面Allow语句里放行的only-allowed-folder下的图片路径。只要请求命中Deny语句的主体、动作、资源三个匹配条件,就会被直接拦截,根本不会进入Allow规则的判断流程。哪怕你把Principal改成指定用户,该用户访问允许路径的请求依然会同时命中Allow和Deny规则,最终被Deny拦截。
S3桶策略默认遵循「隐式拒绝」原则:所有没有被显式Allow的请求,默认都会被拒绝,完全不需要额外写全量Deny语句兜底,这也是你删掉Deny语句后权限正常生效的原因。
直接保留Allow语句即可,修正后的最小可用策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowTargetUserAccessSpecifiedImages", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123123:user/myuser-s3-uploader" }, "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": [ "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.jpg", "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.jpeg", "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.png" ] } ] }
需要注意路径通配符的匹配规则:你当前写的only-allowed-folder/*/*.jpg只会匹配only-allowed-folder下一层子目录内的jpg文件,如果需要覆盖该文件夹下所有层级(包括文件夹根目录、多层嵌套子目录)的对应后缀文件,需要根据实际目录结构补充资源路径,比如增加arn:aws:s3:::my-bucket/only-allowed-folder/*.jpg匹配根目录下的jpg、增加arn:aws:s3:::my-bucket/only-allowed-folder/*/*/*.jpg匹配两层子目录下的jpg,避免因为路径匹配不全导致合法请求被拦截。
如果你的使用场景必须加显式Deny做兜底(比如防止其他绑定到该用户的IAM策略开放了多余S3权限),不能直接写全资源范围的Deny,需要用NotResource字段排除你允许的路径,参考写法:
{ "Sid": "DenyUserAccessToNonAllowedPaths", "Effect": "Deny", "Principal": { "AWS": "arn:aws:iam::123123:user/myuser-s3-uploader" }, "Action": [ "s3:PutObject", "s3:GetObject" ], "NotResource": [ "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.jpg", "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.jpeg", "arn:aws:s3:::my-bucket/only-allowed-folder/*/*.png" ] }
这条Deny的逻辑是:仅当用户访问的资源不在允许列表内时才触发拦截,访问合法路径时不会命中Deny规则,可正常走Allow逻辑。非必要不建议加这类Deny语句,很容易因为通配符匹配范围写错导致权限异常。
预签名URL的权限完全继承生成URL时所用IAM身份的权限,不需要额外在预签名生成逻辑里做后缀限制:
- 只要IAM用户的权限被严格限定在指定路径的三种图片后缀,哪怕前端拿到预签名URL后尝试篡改路径、上传其他后缀的文件,S3服务端会直接拒绝请求,不会放行
- 生成预签名URL时,传入的对象Key必须符合你设定的路径和后缀规则,否则生成的URL对应的资源本身不在用户权限范围内,上传/访问请求都会被拦截
内容的提问来源于stack exchange,提问作者xbmono

