

 适用于 .NET 的 AWS SDK V3 已进入维护模式。

我们建议您迁移到 [适用于 .NET 的 AWS SDK V4](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/welcome.html)。有关如何迁移的更多详细信息和信息，请参阅我们的[维护模式公告](https://aws.amazon.com/blogs/developer/aws-sdk-for-net-v3-maintenance-mode-announcement/)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 Amazon Cognito 验证用户身份
<a name="cognito-apis-intro"></a>

**注意**  
本主题中的信息特定于基于.NET Framework 和 3.3 及更早 适用于 .NET 的 AWS SDK 版本的项目。

使用 Amazon Cognito Identity，您可以为用户创建唯一身份，并对他们进行身份验证，以便安全访问您的 AWS 资源，例如亚马逊 S3 或 Amazon DynamoDB。Amazon Cognito Identity 支持公共身份提供商（如 Amazon、Facebook、Twitter/Digits、Google 或兼容 OpenID Connect 的任何提供商），以及未经身份验证的身份。Amazon Cognito 还支持[已经过开发人员验证的身份](https://aws.amazon.com/blogs/mobile/amazon-cognito-announcing-developer-authenticated-identities/)，借助该身份，您可以注册用户并通过自己的后端身份验证流程对用户进行身份验证，同时仍然使用 Amazon Cognito Sync 同步用户数据和访问 AWS 资源。

有关 [Amazon Cognito](https://aws.amazon.com/cognito/) 的更多信息，请参阅 [Amazon Cognito 开发人员指南](https://docs.aws.amazon.com/cognito/latest/developerguide/)

以下代码示例显示如何轻松使用 Amazon Cognito 身份。[凭证提供程序](cognito-creds-provider.md)示例显示如何创建用户身份并对其进行身份验证。该[CognitoAuthentication 扩展库](cognito-authentication-extension.md)示例展示了如何使用 CognitoAuthentication 扩展库对 Amazon Cognito 用户池进行身份验证。

**Topics**
+ [凭证提供程序](cognito-creds-provider.md)
+ [CognitoAuthentication 扩展库](cognito-authentication-extension.md)

# Amazon Cognito 凭证提供程序
<a name="cognito-creds-provider"></a>

**注意**  
本主题中的信息特定于基于.NET Framework 和 3.3 及更早 适用于 .NET 的 AWS SDK 版本的项目。

 `Amazon.CognitoIdentity.CognitoAWSCredentials`，可在[AWSSDK。 CognitoIdentity](https://www.nuget.org/packages/AWSSDK.CognitoIdentity/) NuGetpack AWS age，是一个凭证对象，它使用 Amazon Cognito 和 AWS Security Token Service (AWS STS) 来检索用于拨打电话的证书。

设置 `CognitoAWSCredentials` 的第一步是创建一个“身份池”。(身份池是用于存储特定于您的账户的用户身份信息的存储区。此信息可跨各种客户端平台、设备和操作系统进行检索，因此，如果用户在手机上开始使用此应用程序不久后又切换到平板电脑，该用户仍然可以使用保留的应用程序信息。您可以通过 Amazon Cognito 控制台创建新的身份池。如果您使用的是此控制台，它还将为您提供您所需的其他信息：
+ 您的账号 - 一个 12 位数字，如 123456789012，这是您账户独有的号码。
+ 未经身份验证的角色 ARN - 未经身份验证的用户将担任的角色。例如，此角色可提供对您的数据的只读权限。
+ 经过身份验证的角色 ARN- 经过身份验证的用户将担任的角色。此角色可提供对您的数据的更广泛的权限。

## 设置 Cognito AWSCredentials
<a name="set-up-cognitoawscredentials"></a>

以下代码示例显示如何设置 `CognitoAWSCredentials`，然后您可使用此凭证以未经身份验证的角色的身份调用 Amazon S3。这使您能够只需要对用户进行身份验证所需的最少量数据即可进行调用。用户权限由角色控制，因此您可以根据需要配置访问权限。

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId,        // Account number
    identityPoolId,   // Identity pool ID
    unAuthRoleArn,    // Role for unauthenticated users
    null,             // Role for authenticated users, not set
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    s3Client.ListBuckets();
}
```

## AWS 以未经身份验证的用户身份使用
<a name="use-aws-as-an-unauthenticated-user"></a>

以下代码示例显示了如何以未经身份验证的用户身份开始使用 AWS ，然后通过 Facebook 进行身份验证并更新凭据以使用 Facebook 凭据。使用此方法，您可以通过经过身份验证的角色授予经过身份验证的用户不同的功能。例如，您可能有一个电话应用程序，该应用程序允许用户匿名查看内容，但在用户使用一个或多个已配置的提供商登录的情况下允许其发帖。

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId, identityPoolId,
    unAuthRoleArn,    // Role for unauthenticated users
    authRoleArn,      // Role for authenticated users
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    // Initial use will be unauthenticated
    s3Client.ListBuckets();

    // Authenticate user through Facebook
    string facebookToken = GetFacebookAuthToken();

    // Add Facebook login to credentials. This clears the current AWS credentials
    // and retrieves new AWS credentials using the authenticated role.
    credentials.AddLogin("graph.facebook.com", facebookAccessToken);

    // This call is performed with the authenticated role and credentials
    s3Client.ListBuckets();
}
```

如果您将 `CognitoAWSCredentials` 对象与属于 适用于 .NET 的 AWS SDK的一部分的 `AmazonCognitoSyncClient` 结合使用，则该对象会提供更多功能。如果您使用的是 `AmazonCognitoSyncClient` 和 `CognitoAWSCredentials`，则无需在使用 `IdentityPoolId` 进行调用时指定 `IdentityId` 和 `AmazonCognitoSyncClient` 属性。这些属性会自动从 `CognitoAWSCredentials` 中进行填入。以下代码示例将对此进行说明以及说明每当 `IdentityId` 的 `CognitoAWSCredentials` 发生更改时通知您的事件。在某些情况下 `IdentityId` 可能会发生更改，例如，当从未经身份验证的用户更改为经过身份验证的用户时。

```
CognitoAWSCredentials credentials = GetCognitoAWSCredentials();

// Log identity changes
credentials.IdentityChangedEvent += (sender, args) =>
{
    Console.WriteLine("Identity changed: [{0}] => [{1}]", args.OldIdentityId, args.NewIdentityId);
};

using (var syncClient = new AmazonCognitoSyncClient(credentials))
{
    var result = syncClient.ListRecords(new ListRecordsRequest
    {
        DatasetName = datasetName
        // No need to specify these properties
        //IdentityId = "...",
        //IdentityPoolId = "..."        
    });
}
```

# Amazon CognitoAuthentication 扩展库示例
<a name="cognito-authentication-extension"></a>

**注意**  
本主题中的信息特定于基于.NET Framework 和 3.3 及更早 适用于 .NET 的 AWS SDK 版本的项目。

 CognitoAuthentication 扩展程序库，可[在 Amazon.Extensions 中找到。 CognitoAuthentication](https://www.nuget.org/packages/Amazon.Extensions.CognitoAuthentication/) NuGet 包，简化了.NET Core 和 Xamarin 开发人员的 Amazon Cognito 用户池的身份验证过程。该库基于 Amazon Cognito 身份提供商 API 构建，可创建和发送用户身份验证 API 调用。

## 使用 CognitoAuthentication 扩展库
<a name="using-the-cognitoauthentication-extension-library"></a>

Amazon Cognito 有一些适用于标准身份验证流程的内置 `AuthFlow` 和 `ChallengeName` 值，以通过安全远程密码（SRP）协议验证用户名和密码。有关身份验证流程的更多信息，请参阅 [Amazon Cognito 用户池身份验证流程](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html)。

以下示例需要这些 `using` 语句：

```
// Required for all examples
using System;
using Amazon;
using Amazon.CognitoIdentity;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;
// Required for the GetS3BucketsAsync example
using Amazon.S3;
using Amazon.S3.Model;
```

### 用户基本身份验证
<a name="use-basic-authentication"></a>

[AmazonCognitoIdentityProviderClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CognitoIdentityProvider/TCognitoIdentityProviderClient.html)使用 An [onymou](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TAnonymousAWSCredentials.html) s 创建AWSCredentials，它不需要签名请求。您无需提供一个区域，如果未提供区域，底层代码将调用 `FallbackRegionFactory.GetRegionEndpoint()`。创建 `CognitoUserPool` 和 `CognitoUser` 对象。使用包含用户密码的 `StartWithSrpAuthAsync` 调用 `InitiateSrpAuthRequest` 方法。

```
public static async void GetCredsAsync()
{
    AmazonCognitoIdentityProviderClient provider =
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest()
    {
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);
    accessToken = authResponse.AuthenticationResult.AccessToken;

}
```

### 使用质询进行身份验证
<a name="authenticate-with-challenges"></a>

通过质询（例如使用 NewPasswordRequired 和多因素身份验证 (MFA)）来继续进行身份验证流程也更加简单。唯一的要求是 CognitoAuthentication 对象、用户的 SRP 密码以及下一个挑战的必要信息，这些信息是在提示用户输入后获取的。以下代码显示了一种在身份验证流程中检查质询类型并获得 MFA 和 NewPasswordRequired 质询的相应响应的方法。

像之前一样执行基本身份验证请求，并且 `await` 一个 `AuthFlowResponse`。当收到响应时，循环访问返回的 `AuthenticationResult` 对象。如果 `ChallengeName` 类型为 `NEW_PASSWORD_REQUIRED`，请调用 `RespondToNewPasswordRequiredAsync` 方法。

```
public static async void GetCredsChallengesAsync()
{
    AmazonCognitoIdentityProviderClient provider = 
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest(){
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);

    while (authResponse.AuthenticationResult == null)
    {
        if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
        {
            Console.WriteLine("Enter your desired new password:");
            string newPassword = Console.ReadLine();

            authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
            {
                SessionID = authResponse.SessionID,
                NewPassword = newPassword
            });
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
        {
            Console.WriteLine("Enter the MFA Code sent to your device:");
            string mfaCode = Console.ReadLine();

            AuthFlowResponse mfaResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
            {
                SessionID = authResponse.SessionID,
                MfaCode = mfaCode

            }).ConfigureAwait(false);
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else
        {
            Console.WriteLine("Unrecognized authentication challenge.");
            accessToken = "";
            break;
        }
    }

    if (authResponse.AuthenticationResult != null)
    {
        Console.WriteLine("User successfully authenticated.");
    }
    else
    {
        Console.WriteLine("Error in authentication process.");
    }
 
}
```

### 身份验证后使用 AWS 资源
<a name="use-aws-resources-after-authentication"></a>

使用 CognitoAuthentication 库对用户进行身份验证后，下一步就是允许该用户访问相应的 AWS 资源。为此，您必须通过 Amazon Cognito 联合身份控制台创建一个身份池。通过将您创建的 Amazon Cognito 用户池指定为提供商并使用其 poolID 和 clientID，您可以允许您的 Amazon Cognito 用户群体用户访问连接到您账户的 AWS 资源。您还可以指定不同的角色来支持未经身份验证的和已经过身份验证的用户访问不同的资源。您可以在 IAM 控制台中更改这些规则，其中，您可以在角色的附加策略的**操作**字段中添加或删除权限。然后，使用相应的身份池、用户池和 Amazon Cognito 用户信息，您可以调用不同的 AWS 资源。以下示例显示了使用用于访问关联的身份池的角色允许的不同 Amazon S3 桶的 SRP 进行用户身份验证

```
public async void GetS3BucketsAsync()
{
    var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);

    string password = "userPassword";

    AuthFlowResponse context = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
    {
        Password = password
    }).ConfigureAwait(false);

    CognitoAWSCredentials credentials =
        user.GetCognitoAWSCredentials("identityPoolID", RegionEndpoint.< YourIdentityPoolRegion >);

    using (var client = new AmazonS3Client(credentials))
    {
        ListBucketsResponse response =
            await client.ListBucketsAsync(new ListBucketsRequest()).ConfigureAwait(false);

        foreach (S3Bucket bucket in response.Buckets)
        {
            Console.WriteLine(bucket.BucketName);
        }
    }
}
```

## 更多身份验证选项
<a name="more-authentication-options"></a>

除了 SRP NewPasswordRequired、和 MFA 之外，扩展库还为 CognitoAuthentication 以下用户提供了更简单的身份验证流程：
+ 自定义- 通过调用 `StartWithCustomAuthAsync(InitiateCustomAuthRequest customRequest)` 启动 
+ RefreshToken -首先致电至 `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` 
+ RefreshTokenSRP-通过拨打以下电话启动 `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` 
+ AdminNoSRP-通过拨打以下电话启动 `StartWithAdminNoSrpAuthAsync(InitiateAdminNoSrpAuthRequest adminAuthRequest)` 

根据您想要的流程调用相应的方法。然后，当质询显示在每个方法调用的 `AuthFlowResponse` 对象中时继续提示用户进行质询。此外，调用相应的响应方法，如适用于 MFA 质询的 `RespondToSmsMfaAuthAsync` 和适用于自定义质询的 `RespondToCustomAuthAsync`。