

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

# 使用用户池中的用户设备
<a name="amazon-cognito-user-pools-device-tracking"></a>

当您使用 Amazon Cognito 用户池 API 登录本地用户池用户时，可以将来自[威胁防护](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-threat-protection.html)的用户活动日志与用户的每台设备相关联，并且如果用户使用的是可信设备，还可以选择让用户跳过多重身份验证（MFA）。对于任何尚未包含设备信息的登录，Amazon Cognito 都会在响应中包含设备密钥。设备密钥的格式为 `Region_UUID`。借助设备密钥、安全远程密码（SRP）库和允许设备身份验证的用户池，您可以提示应用程序中的用户信任当前设备，而不再在登录时提示输入 MFA 代码。

**Topics**
+ [设置记忆设备](#amazon-cognito-user-pools-setting-up-remembered-devices)
+ [获取设备密钥](#user-pools-remembered-devices-getting-a-device-key)
+ [使用设备登录](#user-pools-remembered-devices-signing-in-with-a-device)
+ [查看、更新和忘记设备](#user-pools-remembered-devices-viewing-updating-forgetting)

## 设置记忆设备
<a name="amazon-cognito-user-pools-setting-up-remembered-devices"></a>

借助 Amazon Cognito 用户池，您可以将每个用户的设备与唯一的设备标识符（设备密钥）关联起来。当您在登录时提供设备密钥和执行设备身份验证时，可以使用*可信设备*身份验证流程配置应用程序。在此流程中，您的应用程序可以为用户提供一种选择，使其无需使用 MFA 即可登录，直至由应用程序安全要求或用户首选项确定的某个时间之后。在该段时间后，您的应用程序必须将设备状态更改为*未记住*，并且用户必须通过 MFA 登录，直至他们确认他们希望记住设备。例如，应用程序可能会提示用户信任某台设备 30 天、60 天或 90 天。您可以将此日期存储在自定义属性中，并在该日期更改其设备的记住状态。然后，必须重新提示用户提交 MFA 代码并将设备设置为在成功进行身份验证后再次记住设备。

1. 记住的设备只能在 MFA 处于活动状态的用户池中覆盖 MFA。

当用户使用记住的设备登录时，您必须在其身份验证流程中执行额外的设备身份验证。有关更多信息，请参阅 [使用设备登录](#user-pools-remembered-devices-signing-in-with-a-device)。

在用户池的**登录**菜单的**设备跟踪**下，将用户池配置为记住设备。通过 Amazon Cognito 控制台设置记忆设备功能时，有三种选项供您选择：**Always (始终)**、**User Opt-In (用户选择加入)** 和 **No (否)**。

**请勿记住**  
用户池不会提示用户在登录时记住设备。

**始终记住**  
当应用程序确认用户的设备时，用户池将始终记住该设备，并且不会在将来成功登录设备时返回 MFA 质询。

**用户选择加入**  
当应用程序确认用户的设备后，用户池不会自动抑制 MFA 质询。您必须提示用户选择是否要记住设备。

当您选择**始终记住**或**用户选择加入**时，每次用户从身份不明的设备登录时，Amazon Cognito 都会生成设备标识符密钥和机密。设备密钥是应用程序在用户执行设备身份验证时发送到用户池的初始标识符。

对于每个已确认的用户设备，无论是自动记住还是选择加入，您都可以在每次用户登录时使用设备标识符密钥和机密对设备进行身份验证。

您还可以在[CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html)或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html)API 请求中为用户池配置记忆设备设置。欲了解更多信息，请参阅该[DeviceConfiguration](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-DeviceConfiguration)属性。

Amazon Cognito 用户池 API 为记住的设备提供了额外的操作。

1. [ListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html)并[AdminListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListDevices.html)返回用户的设备密钥及其元数据的列表。

1. [GetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetDevice.html)并[AdminGetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetDevice.html)返回单个设备的设备密钥和元数据。

1. [UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)并将用户的设备[AdminUpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateDeviceStatus.html)设置为已记住或未记住。

1. [ForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgetDevice.html)并从用户的个人资料中[AdminForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminForgetDevice.html)移除已确认的设备。

名称以 `Admin` 开头的 API 操作用于服务器端应用程序，必须使用 IAM 凭证进行授权。有关更多信息，请参阅 [了解 API、OIDC 和托管登录页面身份验证](authentication-flows-public-server-side.md#user-pools-API-operations)。

## 获取设备密钥
<a name="user-pools-remembered-devices-getting-a-device-key"></a>

每当用户使用用户池 API 登录并且身份验证参数中未包含设备密钥作为 `DEVICE_KEY` 时，Amazon Cognito 都会在响应中返回新的设备密钥。在公共客户端应用程序中，将设备密钥放在应用程序存储中，以便您可以将其包含在将来的请求中。在机密服务器端应用程序中，使用用户的设备密钥设置浏览器 Cookie 或其它客户端令牌。

应用程序必须确认设备密钥并提供其它信息，然后用户才能使用其可信设备登录。向 Amazon Cognito 生成[ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html)请求，使用设备密钥、友好名称、密码验证器和盐来确认用户的设备。如果您将用户池配置为选择加入设备身份验证，Amazon Cognito 会在响应您的 `ConfirmDevice` 请求时，提示用户必须选择是否记住当前设备。在[UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)请求中使用用户选择的内容进行回应。

当您确认用户的设备但未将其设置为记住的设备时，Amazon Cognito 会存储关联，但在您提供设备密钥时继续进行非设备登录。设备可以生成对用户安全和故障排除非常有用的日志。已确认但未记住的设备不会利用登录特征，但会利用安全监控日志特征。当您为应用程序客户端激活威胁防护功能并将设备指纹编码到请求中时，Amazon Cognito 会将用户事件与已确认的设备关联起来。

**获取新的设备密钥**

1. 使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 请求开始用户的登录会话。

1. 在收到标记用户登录会话完成的 JSON Web 令牌 (JWTs) [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)之前，使用回复所有身份验证挑战。

1. 在应用程序中，记录 Amazon Cognito 在其 `RespondToAuthChallenge` 或 `InitiateAuth` 响应的 `NewDeviceMetadata` 中返回的值：`DeviceGroupKey` 和 `DeviceKey`。

1. 为用户生成新的 SRP 密钥：盐和密码验证程序。此功能在提供 SRP 库 SDKs 的中可用。

1. 提示用户输入设备名称，或根据用户的设备特征生成一个名称。

1. 在 [ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html)API 请求中提供用户的访问令牌、设备密钥、设备名称和 SRP 密钥。如果用户池设置为**始终记住**设备，则用户的注册已完成。

1. 如果 Amazon Cognito 对于 `ConfirmDevice` 响应了 `"UserConfirmationNecessary": true`，请提示您的用户选择是否要记住该设备。如果他们确认要记住设备，请使用用户的访问令牌、设备密钥和生成 [UpdateDeviceStatus](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateDeviceStatus.html)API 请求`"DeviceRememberedStatus": "remembered"`。

1. 如果您已指示 Amazon Cognito 记住该设备，那么当用户下次登录时，看到的不是 MFA 质询，而是 `DEVICE_SRP_AUTH` 质询。

## 使用设备登录
<a name="user-pools-remembered-devices-signing-in-with-a-device"></a>

将用户的设备配置为记住后，当用户使用相同的设备密钥登录时，Amazon Cognito 不再要求用户提交 MFA 代码。设备身份验证仅用设备身份验证质询取代 MFA 身份验证质询。您不能仅使用设备身份验证登录用户。用户必须首先使用其密码或自定义质询完成身份验证。以下是在记住的设备上对用户进行身份验证的过程。

要在使用[自定义身份验证质询 Lambda 触发器的流程中执行设备身份验证](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html)，请在您的 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API `DEVICE_KEY` 请求中传递参数。在用户成功完成所有质询并且 `CUSTOM_CHALLENGE` 质询返回的 `issueTokens` 值为 `true` 之后，Amazon Cognito 将返回一个最终 `DEVICE_SRP_AUTH` 质询。

**使用设备登录**

1. 从客户端存储中检索用户的设备密钥。

1. 使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 请求开始用户的登录会话。选择一个 `AuthFlow`：`USER_SRP_AUTH`、`REFRESH_TOKEN_AUTH`、`USER_PASSWORD_AUTH` 或 `CUSTOM_AUTH`。在 `AuthParameters` 中，将用户的设备密钥添加到 `DEVICE_KEY` 参数中，并包括所选登录流程所需的其它参数。

   1. 您还可以在对身份验证质询的 `PASSWORD_VERIFIER` 响应的参数中传递 `DEVICE_KEY`。

1. 完成质询响应，直到您在响应中收到 `DEVICE_SRP_AUTH` 质询。

1. 在 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 请求中，发送`USERNAME``DEVICE_KEY`、`DEVICE_SRP_AUTH`和`ChallengeName`的和参数`SRP_A`。

1. Amazon Cognito 以 `DEVICE_PASSWORD_VERIFIER` 质询进行响应。此质询响应包括 `SECRET_BLOCK` 和 `SRP_B` 的值。

1. 使用您的 SRP 库，生成并提交 `PASSWORD_CLAIM_SIGNATURE`、`PASSWORD_CLAIM_SECRET_BLOCK`、`TIMESTAMP`、`USERNAME` 和 `DEVICE_KEY` 参数。在其它 `RespondToAuthChallenge` 请求中提交这些内容。

1. 完成其他挑战，直到收到用户的挑战 JWTs。

以下伪代码演示如何计算 `DEVICE_PASSWORD_VERIFIER` 质询响应的值。要对设备进行 SRP 身份验证，请为用户生成一个*新*的 SRP 密钥：新的高熵密码 `DeviceSecret`、加密盐及关联的密码验证程序。这些值不同于用于用户 SRP 身份验证的密码、加密盐和验证程序。它们仅用于设备身份验证，并且仅存储在设备上。用于为用户设备生成 SRP 密钥的功能可在不同版本的 [SRP 库](https://github.com/secure-remote-password/implementations)中找到。 SDKs

```
PASSWORD_CLAIM_SECRET_BLOCK = SECRET_BLOCK
TIMESTAMP = "Tue May 7 00:09:40 UTC 2025"
k = SHA256(N || g) as a non-negative integer in big-endian
u = SHA256(SRP_A || SRP_B) as a non-negative integer in big-endian
x = SHA256(salt || SHA256(DeviceGroupKey || DeviceKey || ":" || DeviceSecret)) as a non-negative integer in big-endian
S_USER = (SRP_B - k * g^x)^(a + u * x) % N
K_USER = HKDF_HMAC_SHA256(salt=u, ikm=S_USER, info="Caldera Derived Key", length=16 bytes)
PASSWORD_CLAIM_SIGNATURE = Base64(HMAC_SHA256(key=K_USER, message=(DeviceGroupKey || DeviceKey || PASSWORD_CLAIM_SECRET_BLOCK || TIMESTAMP)))
```

## 查看、更新和忘记设备
<a name="user-pools-remembered-devices-viewing-updating-forgetting"></a>

您可以使用 Amazon Cognito API 在应用程序中实现以下特征。

1. 显示有关用户的当前设备的信息。

1. 显示用户的所有设备的列表。

1. 忘记设备。

1. 更新设备记住的状态。

授权以下描述中的 API 请求的访问令牌必须包含 `aws.cognito.signin.user.admin` 范围。Amazon Cognito 会将此范围的声明添加到您使用 Amazon Cognito 用户池 API 生成的所有访问令牌中。第三方 IdPs 必须为其向 Amazon Cognito 进行身份验证的用户单独管理设备和 MFA。在托管登录中，您可以请求 `aws.cognito.signin.user.admin` 范围，但是托管登录会自动将设备信息添加到高级安全用户日志中，而不提供记住设备的功能。

**显示有关设备的信息**  
您可以查询有关用户设备的信息，以确定设备当前是否仍在使用中。例如，您可能希望在记住的设备已有 90 天未登录后将其停用。
+ 要在公共客户端应用程序中显示用户的设备信息，请在 [GetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetDevice.html)API 请求中提交用户的访问密钥和设备密钥。
+ 要在机密客户端应用程序中显示用户的设备信息，请使用 AWS 凭据签署 [AdminGetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetDevice.html)API 请求并提交用户的用户名、设备密钥和用户池。

**显示用户的所有设备的列表**  
您可以显示用户的所有设备及其属性的列表。例如，您可能要验证当前设备是否与记住的设备相匹配。
+ 在公共客户端应用程序中，在 [ListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html)API 请求中提交用户的访问令牌。
+ 在机密客户端应用程序中，使用 AWS 凭据签署 [AdminListDevices](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminListDevices.html)API 请求并提交用户的用户名和用户池。

**忘记设备**  
您可以删除用户的设备密钥。当您确定您的用户不再使用设备时，或者当您检测到异常活动并希望提示用户再次完成 MFA 时，您可能需要这样做。要稍后再次注册设备，必须生成并存储新的设备密钥。
+ 在公共客户端应用程序中，在 [ForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgetDevice.html)API 请求中提交用户的设备密钥和访问令牌。
+ 在机密客户端应用程序中，在 [AdminForgetDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminForgetDevice.html)API 请求中提交用户的设备密钥和访问令牌。