Amplify Flutter中已通过Cognito登录仍无法访问S3对象如何解决
问题根因
- 生成的S3访问URL未携带鉴权签名:你当前代码生成的是S3原生静态URL,浏览器直接访问时属于匿名请求,非公开对象默认会被S3拒绝,这是最常见的原因。
- Cognito认证角色缺少S3访问权限:登录用户关联的IAM角色未配置对应S3桶的
s3:GetObject权限,即使请求带签名也会被拦截。 - 上传与获取URL时的访问级别不匹配:Amplify Storage支持
private/protected/public三种访问级别,上传和读取时指定的级别不一致会导致鉴权失败。 - S3桶策略存在额外限制:桶配置了拦截Cognito身份访问的规则,覆盖了IAM角色的权限配置。
解决方案
- 调整getUrl方法生成带签名的预签名URL
调用Amplify.Storage.getUrl时显式配置参数,生成带鉴权签名的有时效性URL,无需将对象设为公开即可访问,修改后的代码如下:
Future<String> getUrlS3(String UploadKey) async { try { GetUrlResult result = await Amplify.Storage.getUrl( key: UploadKey, options: GetUrlOptions( // 自定义签名URL有效期,最长可设为7天 expiresIn: Duration(minutes: 30), // 和上传时的访问级别保持一致,未特殊指定的话默认是private accessLevel: StorageAccessLevel.private ) ); return result.url.toString(); } on StorageException catch (e) { return e.message; } }
- 配置Cognito认证角色的S3访问权限
在AWS IAM控制台找到你Cognito用户池关联的认证用户IAM角色,为该角色添加如下权限策略,替换其中的S3桶名为你实际使用的桶名:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的S3桶名/*" } ] }
- 匹配访问级别
确认上传对象时指定的accessLevel参数和获取URL时的参数一致:public级别允许匿名访问,protected允许所有认证用户访问,private仅允许上传者本人访问。 - 检查S3桶策略
确认桶策略没有限制Cognito身份的访问,不要设置仅允许特定IAM用户访问、强制匿名访问的规则。
内容的提问来源于stack exchange,提问作者Vikram Sharma
相关产品推荐
相关产品推荐

