You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 13:35:22