如何使用C#/.Net下载AWS S3文件并解决角色权限导致的Access Denied错误
错误根因
你当前直接使用IAM用户的永久密钥初始化S3客户端,没有切换到拥有S3对象访问权限的角色,所以触发Access Denied报错,和网页端需要切换角色才能下载的逻辑一致。
代码修改步骤
- 先安装依赖NuGet包:除已有的
AWSSDK.S3外,额外安装AWSSDK.SecurityToken包,用于调用AWS STS服务完成角色切换获取临时访问凭证 - 先通过STS接口调用
AssumeRole方法,获取目标角色的临时访问密钥、会话令牌 - 使用返回的临时凭证初始化
AmazonS3Client,再发起S3对象下载请求 - 修正原代码中二进制文件读取逻辑:图片为二进制资源,不可用
StreamReader按文本读取,直接将响应流写入本地文件即可避免文件损坏
完整修改后代码
using Amazon; using Amazon.Runtime; using Amazon.S3; using Amazon.S3.Model; using Amazon.SecurityToken; using Amazon.SecurityToken.Model; using System; using System.IO; using System.Threading.Tasks; namespace Amazon.DocSamples.S3 { class GetObjectTest { private const string bucketName = "My_Bucket_Name"; // 替换为实际桶名 private const string keyName = "123/456/789.jpg"; // 替换为实际对象路径 private const string targetRoleArn = "arn:aws:iam::你的账号ID:role/你的角色名称"; // 替换为有权限的角色ARN private const string roleSessionName = "S3DownloadSession"; // 自定义会话名称,可随意填写 private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2; // 替换为实际桶区域 private static IAmazonS3 s3Client; static string accessKey = "***AccessKey***"; // 替换为你的IAM用户访问密钥 static string secretKey = "***SecretKey***"; // 替换为你的IAM用户私密密钥 public static void Main() { // 先切换角色获取临时凭证 var credentials = AssumeTargetRoleAsync().GetAwaiter().GetResult(); // 使用临时凭证初始化S3客户端 s3Client = new AmazonS3Client(credentials, bucketRegion); ReadObjectDataAsync().Wait(); } /// <summary> /// 调用STS服务切换角色,获取临时凭证 /// </summary> static async Task<Credentials> AssumeTargetRoleAsync() { using var stsClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, bucketRegion); var assumeRoleRequest = new AssumeRoleRequest { RoleArn = targetRoleArn, RoleSessionName = roleSessionName, // 可根据需要设置临时凭证有效期,默认3600秒,最长可设置为角色允许的最大时长 DurationSeconds = 3600 }; var response = await stsClient.AssumeRoleAsync(assumeRoleRequest); return response.Credentials; } static async Task ReadObjectDataAsync() { GetObjectRequest request = new GetObjectRequest { BucketName = bucketName, Key = keyName }; using (GetObjectResponse response = await s3Client.GetObjectAsync(request)) using (Stream responseStream = response.ResponseStream) using (var fileStream = new FileStream(Path.GetFileName(keyName), FileMode.Create, FileAccess.Write)) { string title = response.Metadata["x-amz-meta-title"]; string contentType = response.Headers["Content-Type"]; Console.WriteLine("Object metadata, Title: {0}", title); Console.WriteLine("Content type: {0}", contentType); // 直接将响应流写入本地文件,适配二进制图片资源 await responseStream.CopyToAsync(fileStream); Console.WriteLine($"文件已下载至:{Path.GetFullPath(Path.GetFileName(keyName))}"); } } } }
前置权限校验说明
- 你使用的原始IAM用户必须拥有
sts:AssumeRole权限,允许扮演目标角色 - 目标角色的信任策略中必须添加你的IAM用户ARN作为可信任实体,允许该用户切换角色
- 目标角色的权限策略中必须配置对应S3桶、对象路径的
s3:GetObject访问权限
内容的提问来源于stack exchange,提问作者Iraj
相关产品推荐
相关产品推荐

