

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

# 管理用户存在错误响应
<a name="cognito-user-pool-managing-errors"></a>

Amazon Cognito 支持自定义由用户池返回的错误响应。自定义错误响应可用于用户创建和身份验证、密码恢复和确认操作。

使用用户池应用程序客户端的 `PreventUserExistenceErrors` 设置，以启用或禁用用户存在相关错误。当您使用 Amazon Cognito 用户池 API 创建新的应用程序时，默认情况下 `PreventUserExistenceErrors` 为 `LEGACY` 或禁用。在 Amazon Cognito 控制台中，默认选定**防止用户已存在错误**选项（`PreventUserExistenceErrors` 设置为 `ENABLED`）。要更新 `PreventUserExistenceErrors` 配置，请执行以下操作之一：
+ 在 [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html) API 请求中将 `PreventUserExistenceErrors` 的值更改为 `ENABLED` 和 `LEGACY`。
+ 在 Amazon Cognito 控制台中编辑应用程序客户端，并将**防止用户已存在错误**的状态更改为选定（`ENABLED`）和已取消选择（`LEGACY`）。

当此属性的值为 `LEGACY` 时，当用户尝试使用您的用户池中不存在的用户名登录时，应用程序客户端会返回 `UserNotFoundException` 错误响应。

当此属性的值为 `ENABLED` 时，应用程序客户端不会通过 `UserNotFoundException` 错误来透露您的用户池中不存在某个用户账户。当 `PreventUserExistenceErrors` 配置为 `ENABLED` 时，如果您提交一个不存在的用户名请求，会产生以下效果：
+ Amazon Cognito 会使用非特定信息响应 API 请求，否则其响应可能会泄露存在有效的用户。
+ Amazon Cognito 会向密码重置请求以及使用*除* [基于选择的身份验证](authentication-flows-selection-sdk.md#authentication-flows-selection-choice)（`USER_AUTH`）之外的身份验证流程（例如 `USER_SRP_AUTH` 或 `CUSTOM_AUTH`）的身份验证请求，返回通用的身份验证失败响应。错误响应告知您用户名或密码不正确。
+ 对于基于选择的身份验证请求，Amazon Cognito 会从用户池允许的质询类型中随机选择一种进行响应。您的用户池可能会返回通行密钥、一次性密码或密码质询。
+ Amazon Cognito 账户确认和密码恢复的行为在返回表示代码已发送到模拟传送介质的响应和返回错误之间交 APIs 替进行。`InvalidParameterException`

以下信息详细说明了 `PreventUserExistenceErrors` 设置为 `ENABLED` 时用户池操作的行为。

## 身份验证和用户创建操作
<a name="cognito-user-pool-managing-errors-user-auth"></a>

您可以在用户名密码和安全远程密码（SRP）身份验证中配置错误响应。您还可以对使用自定义身份验证返回的错误进行自定义。基于选择的身份验证不受您的 `PreventUserExistenceErrors` 配置的影响。身份验证流程中的用户存在性披露细节

**基于选择的身份验证**  
在 `USER_AUTH` 基于选择的身份验证流程中，Amazon Cognito 会根据用户池配置和用户的属性，从可用的主身份验证因素中返回一个质询。此身份验证流程可以返回密码、安全远程密码 (SRP)、 WebAuthn (passkey)、SMS 一次性密码 (OTP) 或电子邮件 OTP 质询。当 `PreventUserExistenceErrors` 启用时，Amazon Cognito 会向不存在的用户发出质询，要求他们完成一种或多种可用的身份验证形式。当 `PreventUserExistenceErrors` 禁用时，Amazon Cognito 会返回 `UserNotFound` 异常。

**用户名和密码身份验证**  
当 `PreventUserExistenceErrors` 启用时，身份验证流程 `ADMIN_USER_PASSWORD_AUTH`、`USER_PASSWORD_AUTH` 以及 `USER_AUTH` 的 `PASSWORD` 流程会返回 `NotAuthorizedException`，附带 `Incorrect username or password` 消息。当 `PreventUserExistenceErrors` 禁用时，这些流会返回 `UserNotFoundException`。

**基于安全远程密码（SRP）的身份验证**  
作为最佳实践，应仅在没有配置电子邮件地址、电话号码或首选用户名[别名属性](user-pool-settings-attributes.md#user-pool-settings-aliases)的用户池中，对 `USER_SRP_AUTH` 或 `USER_AUTH` 中的 `PASSWORD_SRP` 流程实现 `PreventUserExistenceErrors`。在 SRP 身份验证流程中，具有别名属性的用户可能不会受到用户存在性隐藏的影响。用户名密码身份验证流程（`ADMIN_USER_PASSWORD_AUTH`、`USER_PASSWORD_AUTH` 和 `USER_AUTH` `PASSWORD` 质询）能够完全隐藏来自别名属性的用户存在性信息。  
当有人使用应用程序客户端未知的用户名尝试 SRP 登录时，Amazon Cognito 会在第一步返回一个模拟响应，如 [RFC 5054](https://tools.ietf.org/html/rfc5054#section-2.5.1.3) 所述。Amazon Cognito 始终针对相同的用户名和用户池组合返回相同的盐值以及 [UUID](cognito-terms.md#terms-uuid) 格式的内部用户 ID。当您发送带有密码证明的 `RespondToAuthChallenge` API 时，Amazon Cognito 在用户名或密码不正确时返回一个通用 `NotAuthorizedException` 错误。有关实施 SRP 身份验证的更多信息，请参阅[使用永久密码和安全有效载荷登录](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-srp)。  
如果您使用基于验证的别名属性，并且不可改变的用户名格式不是 [UUID](cognito-terms.md#terms-uuid)，则可以模拟使用用户名和密码身份验证的通用响应。

**自定义身份验证质询 Lambda 触发器**  
当用户尝试使用 `CUSTOM_AUTH` 身份验证流程登录但其用户名未找到时，Amazon Cognito 会调用[自定义身份验证质询 Lambda 触发器](user-pool-lambda-challenge.md)。输入事件中包含一个名为 `UserNotFound` 的布尔值参数，对于任何不存在的用户，该参数值为 `true`。此参数会出现在用户池发送给创建、定义和验证身份验证质询 Lambda 函数的请求事件中，这些函数构成自定义身份验证架构。在 Lambda 函数逻辑中检查该标识后，您可以为不存在的用户模拟自定义身份验证质询。

**身份验证前 Lambda 触发器**  
当用户尝试登录但其用户名未找到时，Amazon Cognito 会调用[身份验证前触发器](user-pool-lambda-pre-authentication.md)。输入事件中包含一个 `UserNotFound` 参数，对于任何不存在的用户，该参数值为 `true`。

以下列表描述了 `PreventUserExistenceErrors` 对用户账户创建的影响。用户创建流程中的用户存在性披露细节

**SignUp**  
当已使用用户名时，`SignUp` 操作始终返回 `UsernameExistsException`。如果在您的应用程序中注册用户时，您不希望 Amazon Cognito 为电子邮件地址和电话号码返回 `UsernameExistsException` 错误，请使用基于验证的别名属性。有关别名的更多信息，请参阅[自定义登录属性](user-pool-settings-attributes.md#user-pool-settings-aliases)。  
有关 Amazon Cognito 如何阻止使用 `SignUp` API 请求来发现用户池中用户的示例，请参阅 [在注册时防止出现电子邮件地址和电话号码的 `UsernameExistsException` 错误](#cognito-user-pool-managing-errors-prevent-userexistence-errors)。

**导入的用户**  
如果 `PreventUserExistenceErrors` 已启用，则在对导入的用户进行身份验证期间，将返回通用 `NotAuthorizedException` 错误，指示用户名或密码不正确，而不是返回 `PasswordResetRequiredException`。请参阅[要求导入的用户重置密码](cognito-user-pools-using-import-tool.md#cognito-user-pools-using-import-tool-password-reset)了解更多信息。

**迁移用户 Lambda 触发器**  
当 Lambda 触发器在原始事件上下文中设置了空响应时，Amazon Cognito 将为不存在的用户返回模拟响应。有关更多信息，请参阅 [利用用户迁移 Lambda 触发器导入用户](cognito-user-pools-import-using-lambda.md)。

### 在注册时防止出现电子邮件地址和电话号码的 `UsernameExistsException` 错误
<a name="cognito-user-pool-managing-errors-prevent-userexistence-errors"></a>

以下示例演示了在用户池中配置别名属性时，如何在对 `SignUp` API 请求的响应中，防止重复的电子邮件地址和电话号码生成 `UsernameExistsException` 错误。您必须在创建用户池时使用电子邮件地址或电话号码作为别名属性。有关更多信息，请参阅[用户池属性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-aliases)的*自定义登录属性* 部分。

1. Jie 注册了一个新的用户名，还提供了电子邮件地址 `jie@example.com`。Amazon Cognito 将向其电子邮件地址发送一个代码。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp sign-up --client-id 1234567890abcdef0 --username jie --password PASSWORD --user-attributes Name="email",Value="jie@example.com"
   ```

   **响应示例**

   ```
   {
       "UserConfirmed": false, 
       "UserSub": "<subId>", 
       "CodeDeliveryDetails": {
           "AttributeName": "email", 
           "Destination": "j****@e****", 
           "DeliveryMedium": "EMAIL"
       }
   }
   ```

1. Jie 提供了发送过来的代码，确认其拥有该电子邮件地址。这样就完成了用户注册。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=jie --confirmation-code xxxxxx
   ```

1. Shirley 注册了一个新的用户账户并提供了电子邮件地址 `jie@example.com`。Amazon Cognito 不会返回 `UsernameExistsException` 错误，而是向 Jie 的电子邮件地址发送确认码。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp sign-up --client-id 1234567890abcdef0 --username shirley --password PASSWORD --user-attributes Name="email",Value="jie@example.com"
   ```

   **响应示例**

   ```
   {
       "UserConfirmed": false, 
       "UserSub": "<new subId>", 
       "CodeDeliveryDetails": {
           "AttributeName": "email", 
           "Destination": "j****@e****", 
           "DeliveryMedium": "EMAIL"
       }
   }
   ```

1. 在另一种情况下，Shirley 拥有对 `jie@example.com` 的所有权。Shirley 收到了 Amazon Cognito 发送到 Jie 电子邮件地址的代码，并尝试确认该账户。

   ** AWS CLI 命令示例**

   ```
   aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=shirley --confirmation-code xxxxxx
   ```

   **响应示例**

   ```
   An error occurred (AliasExistsException) when calling the ConfirmSignUp operation: An account with the email already exists.
   ```

尽管已将 `jie@example.com` 分配给现有用户，Amazon Cognito 不会对 Shirley 的 `aws cognito-idp sign-up` 请求返回错误。在 Amazon Cognito 返回错误响应之前，Shirley 必须证明对该电子邮件地址的所有权。在具有别名属性的用户池中，此行为会阻止使用公共 `SignUp` API 来检查是否存在具有给定电子邮件地址或电话号码的用户。

此行为与 Amazon Cognito 向使用现有用户名的 `SignUp` 请求返回的响应不同，如以下示例所示。尽管 Shirley 从此回复中得知已经存在具有用户名 `jie` 的用户，但他们并不知道与该用户关联的任何电子邮件地址或电话号码。

**示例 CLI 命令**

```
aws cognito-idp sign-up --client-id 1example23456789 --username jie --password PASSWORD
      --user-attributes Name="email",Value="shirley@example.com"
```

**响应示例**

```
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
```

## 密码重置操作
<a name="cognito-user-pool-managing-errors-password-reset"></a>

当您防止出现用户存在错误时，Amazon Cognito 会对用户密码重置操作返回以下响应。

**ForgotPassword**  
当找不到用户、用户已停用或没有经过验证的传送机制来恢复其密码时，Amazon Cognito 会为用户返回 `CodeDeliveryDetails` 以及模拟的传递媒介。模拟的传递媒介由用户池的输入用户名格式和验证设置决定。

**ConfirmForgotPassword**  
Amazon Cognito 为不存在或已禁用的用户返回 `CodeMismatchException` 错误。如果在使用 `ForgotPassword` 时不请求代码，Amazon Cognito 将返回 `ExpiredCodeException` 错误。

## 确认操作
<a name="cognito-user-pool-managing-errors-confirmation"></a>

当您防止出现用户存在错误时，Amazon Cognito 会对用户确认和验证操作返回以下响应。

**ResendConfirmationCode**  
Amazon Cognito 为已禁用或不存在的用户返回 `CodeDeliveryDetails`。Amazon Cognito 会向现有用户的电子邮件或电话发送确认码。

**ConfirmSignUp**  
 如果代码已过期，则将返回 `ExpiredCodeException`。当用户未被授权时，Amazon Cognito 返回 `NotAuthorizedException`。1如果代码与服务器期望的代码不匹配，则 Amazon Cognito 返回 `CodeMismatchException`。