使用AWS SDK for .NET通过Cognito用户池、身份池安全访问AWS资源遇阻
问题描述
我需要通过用户池和身份池,使用AWS SDK for .NET安全访问AWS S3存储桶和DynamoDB。目前已实现用户登录方法SimpleLogin:
public static async Task<bool> SimpleLogin(string username, string password) { bool loginSuccess = false; string accessToken; UserCredentials user1 = new UserCredentials() { Username = username, Password = password }; var creds = new BasicAWSCredentials(IAMAccessID, IAMSecretID); AmazonCognitoIdentityProviderClient provider = new AmazonCognitoIdentityProviderClient(creds, RegionEndpoint.EUWest2); CognitoUserPool userPool = new CognitoUserPool(poolID, clientID, provider); CognitoUser user = new CognitoUser(user1.Username, clientID, userPool, provider); InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest() { Password = user1.Password }; try { AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false); if (authResponse.AuthenticationResult != null) { Debug.WriteLine("User successfully authenticated."); loginSuccess = true; } else { Debug.WriteLine("Error in authentication process."); loginSuccess = false; } } catch (Amazon.CognitoIdentityProvider.Model.NotAuthorizedException nae) { //bad username or password loginSuccess = false; } catch (Exception ex) { //any other exception } return loginSuccess; }
我理解下一步需要用返回的访问令牌访问身份池,进而访问S3存储桶和DynamoDB,但找不到相关示例。我编写了创建Cognito凭证并尝试访问存储桶的代码:
CognitoAWSCredentials c = new CognitoAWSCredentials(identityPoolID, RegionEndpoint.EUWest2); using (var client = new AmazonS3Client(c, RegionEndpoint.EUWest2)) { var dir = new S3DirectoryInfo(client, "recordings", "924f22fb-2694-4fce-b85a-47b1c59b8466"); foreach (IS3FileSystemInfo file in dir.GetFileSystemInfos()) { Debug.WriteLine(file.Name); Debug.WriteLine(file.Extension); Debug.WriteLine(file.LastWriteTime); } ListBucketsResponse response = await client.ListBucketsAsync(new ListBucketsRequest()).ConfigureAwait(false); foreach (S3Bucket bucket in response.Buckets) { Debug.WriteLine(bucket.BucketName); } }
但遇到两个问题:
- 创建
S3DirectoryInfo对象时出现400错误; - 创建身份池凭证时未要求传入访问令牌,这让我感到困惑。
解决方案
1. 正确关联用户池认证结果到身份池
你当前创建CognitoAWSCredentials的方式没有绑定用户池的登录状态,身份池会默认使用未认证身份(权限通常受限)。必须传入用户池返回的IdToken来关联已认证用户:
首先修改SimpleLogin方法,返回完整的认证结果(而非仅布尔值):
public static async Task<AuthenticationResultType> SimpleLogin(string username, string password) { UserCredentials user1 = new UserCredentials() { Username = username, Password = password }; var creds = new BasicAWSCredentials(IAMAccessID, IAMSecretID); AmazonCognitoIdentityProviderClient provider = new AmazonCognitoIdentityProviderClient(creds, RegionEndpoint.EUWest2); CognitoUserPool userPool = new CognitoUserPool(poolID, clientID, provider); CognitoUser user = new CognitoUser(user1.Username, clientID, userPool, provider); InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest() { Password = user1.Password }; try { AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false); if (authResponse.AuthenticationResult != null) { Debug.WriteLine("User successfully authenticated."); return authResponse.AuthenticationResult; } } catch (Amazon.CognitoIdentityProvider.Model.NotAuthorizedException nae) { Debug.WriteLine("Invalid username or password."); } catch (Exception ex) { Debug.WriteLine($"Authentication error: {ex.Message}"); } return null; }
然后用认证结果初始化CognitoAWSCredentials:
// 先完成用户登录 var authResult = await SimpleLogin("your-username", "your-password"); if (authResult == null) { Debug.WriteLine("Login failed"); return; } // 绑定用户池认证信息到身份池凭证 var cognitoCreds = new CognitoAWSCredentials( identityPoolID, RegionEndpoint.EUWest2, authResult.IdToken, authResult.AccessToken, authResult.RefreshToken, new AmazonCognitoIdentityProviderClient( new BasicAWSCredentials(IAMAccessID, IAMSecretID), RegionEndpoint.EUWest2) ); // 使用绑定后的凭证创建S3客户端 using (var s3Client = new AmazonS3Client(cognitoCreds, RegionEndpoint.EUWest2)) { // 执行S3操作... }
2. 解决S3DirectoryInfo的400错误
400错误主要由以下原因导致,逐一排查:
- 权限不足:确认身份池的已认证用户角色拥有访问
recordings桶及前缀924f22fb-2694-4fce-b85a-47b1c59b8466的权限,比如s3:ListBucket、s3:GetObject等。 - 参数错误:检查
S3DirectoryInfo的参数是否正确,第一个参数是存储桶名,第二个是对象前缀,避免前缀以斜杠开头/结尾的格式问题。 - 区域不匹配:确认存储桶所在区域与代码中指定的
RegionEndpoint.EUWest2一致,跨区域访问S3可能触发格式错误。
另外,ListBuckets操作需要单独的高权限,若业务不需要列出所有桶,建议移除该代码,减少权限要求。
内容的提问来源于stack exchange,提问作者Nick Wright
相关产品推荐
相关产品推荐

