注册并确认用户账户 - Amazon Cognito
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

注册并确认用户账户

可通过以下任一方法将用户账户添加到您的用户池中:

自行注册的用户必须得到确认才可登录。导入和创建的用户已经过确认,但他们必须在首次登录时创建自己的密码。以下部分将介绍确认过程以及电子邮件和电话验证。

用户账户确认概览

下图阐明了确认过程:


        当用户输入确认代码时,将自动验证电子邮件或电话。

用户账户可以处于以下任一状态:

已注册(未确认)

用户已成功注册,但在用户账户得到确认之前无法登录。在此状态下,用户已启用,但未得到确认。

自行注册的新用户由此状态开始。

已确认

用户账户已确认,用户可以登录。当用户输入代码或点击电子邮件链接以确认其用户账户时,系统将自动验证电子邮件或电话号码。代码或链接的有效期为 24 小时。

如果管理员或预注册 Lambda 触发器确认了用户账户,则可能没有与该账户关联的经验证的电子邮件或电话号码。

需要重置密码

用户账户已确认,但用户必须请求代码并重置其密码,然后才可以登录。

由管理员或开发人员导入的用户账户以此状态开始。

强制更改密码

用户账户已确认,用户可以使用临时密码进行登录。但在首次登录时,用户必须将其密码更改为新值,然后才能执行任何其他操作。

由管理员或开发人员创建的用户账户以此状态开始。

禁用

在可以删除用户账户之前,必须禁用该用户的登录访问权限。

在注册时验证联系人信息

当新用户注册您的应用程序时,您可能希望他们提供至少一种联系方式。例如,利用用户的联系人信息,您可以:

  • 在用户选择重置其密码时发送临时密码。

  • 在更新用户的个人信息或财务信息后向用户发送通知。

  • 发送促销信息(例如,特别优惠或折扣)。

  • 发送账户摘要或账单提醒。

对于像这样的使用案例,将消息发送到经过验证的目的地非常重要。否则,您可能会将消息发送到错误键入的无效电子邮件地址或电话号码。或者更糟糕的是,您可能会将敏感信息发送给冒充您的用户的坏人。

为了帮助确保您仅将消息发送给正确的人员,请配置您的 Amazon Cognito 用户池以使用户在注册时必须提供以下内容:

  1. 一个电子邮件地址或电话号码。

  2. Amazon Cognito 发送到该电子邮件地址或电话号码的验证码。如果 24 小时后,您的用户代码或链接不再有效,请调用 ResendConfirmationCode API 操作以生成并发送新代码或链接。

通过提供验证码,用户可以证明他们有权访问收到该代码的邮箱或手机。在用户提供该代码后,Amazon Cognito 将通过以下方式更新用户池中的用户相关信息:

  • 将用户的状态设置为 CONFIRMED

  • 更新用户的属性以指示已验证电子邮件地址或电话号码。

要查看此信息,您可以使用 Amazon Cognito 控制台。或者,您可以使用 AdminGetUser API 操作、带 admin-get-user 的 Amazon CLI 命令或某个 Amazon 开发工具包中的相应操作。

如果用户具有经验证的联系方式,Amazon Cognito 会在用户请求重置密码时自动向其发送消息。

配置您的用户池以要求电子邮件或手机验证

验证用户的电子邮件地址和电话号码时,确保可以联系到用户。在 Amazon Web Services Management Console中完成以下步骤以配置用户池,要求用户确认其电子邮件地址或电话号码。

注意

如果您的账户中还没有用户池,请参阅用户池入门

配置用户池
  1. 导航到 Amazon Cognito 控制台。如果出现提示,请输入 Amazon 凭证。

  2. 从导航窗格中选择用户池。从列表中选择一个现有用户池,或创建一个用户池

  3. 选择登录体验选项卡,然后找到属性验证和用户账户确认。选择编辑

  4. Cognito 辅助验证和确认下,选择是否允许 Cognito 自动发送消息以进行验证和确认。启用此设置后,当用户注册或您创建用户配置文件时,Amazon Cognito 会向您选择的用户联系人属性发送消息。为验证属性并确认登录的用户配置文件,Amazon Cognito 会通过消息向用户发送代码或链接。用户随后必须在您的 UI 中输入相应代码,这样,您的应用才能在 ConfirmSignUpAdminConfirmSignUp API 请求中对其进行确认。

    注意

    您还可以禁用 Cognito 辅助验证和确认并使用经过身份验证的 API 操作或 Lambda 触发器验证属性并确认用户。

    如果您选择此选项,则 Amazon Cognito 不会在用户注册时发送验证码。如果您要使用自定义身份验证流程验证至少一种联系方式,而不使用来自 Amazon Cognito 的验证码,请选择此选项。例如,您可以使用一个预注册 Lambda 触发器,该触发器将自动验证属于特定域的电子邮件地址。

    如果您不验证用户的联系人信息,用户可能无法使用您的应用程序。请记住,用户需要经验证的联系人信息才能:

    • 重置密码 – 当用户在您的应用程序中选择调用 ForgotPassword API 操作的选项时,Amazon Cognito 会将临时密码发送到用户的电子邮件地址或电话号码。Amazon Cognito 仅在用户具有至少一个经验证的联系方式时发送此密码。

    • 通过使用电子邮箱地址或电话号码作为别名进行登录 – 如果您将用户池配置为允许这些别名,则用户只能在别名经过验证后使用别名进行登录。有关更多信息,请参阅 自定义登录属性

  5. 选择您的要验证的属性

    发送 SMS 消息,验证电话号码

    Amazon Cognito 将在用户注册时通过 SMS 消息发送验证码。如果您通常通过 SMS 消息与用户通信,请选择此选项。例如,如果您要发送交付通知、约会确认或提醒,则将需要使用经过验证的电话号码。确认账户时,用户电话号码将成为已验证属性;您必须采取其它操作来验证用户电子邮件地址并与其进行通信。

    发送电子邮件消息,验证电子邮件地址

    Amazon Cognito 将在用户注册时通过电子邮件发送验证码。如果您通常通过电子邮件与用户通信,请选择此选项。例如,如果您要发送账单、订单摘要或特别优惠,则将需要使用经过验证的电子邮件地址。确认账户时,用户电子邮件地址将成为已验证属性;您必须采取其它操作来验证用户电话号码并与其进行通信。

    如果电话号码可用,则发送 SMS 消息,否则发送电子邮件

    如果您不要求所有用户都拥有相同的经验证的联系方式,请选择此选项。在这种情况下,您的应用程序中的注册页面可能会要求用户仅验证其首选联系方式。当 Amazon Cognito 发送验证码时,会将该代码发送到来自您应用程序的 SignUp 请求中提供的联系方式。如果用户同时提供了电子邮件地址和电话号码,并且您的应用程序在 SignUp 请求中提供了这两种联系方式,Amazon Cognito 将仅向电话号码发送验证码。

    如果您要求用户同时验证电子邮件地址和电话号码,则选择此选项。Amazon Cognito 将在用户注册时验证一种联系方式,而且您的应用程序必须在用户登录后验证另一种联系方式。有关更多信息,请参阅 在您要求用户确认电子邮件地址和电话号码的情况下

  6. 选择保存更改

使用电子邮件或电话验证的身份验证流程

如果您的用户池要求用户验证其联系人信息,则当用户注册时,您的应用程序必须促进以下流程:

  1. 用户通过输入用户名称、电话号码和/或电子邮件地址及其他可能属性,在您的应用程序中进行注册。

  2. Amazon Cognito 服务接收来自应用程序的注册请求。验证该请求包含注册所需的所有属性后,该服务将完成注册过程并向用户的手机(通过 SMS 消息)或电子邮件发送确认码。代码的有效期为 24 小时

  3. 该服务向应用程序返回信息,表示注册过程已完成且用户账户正等待确认。响应中包含关于确认代码所发送到位置的信息。此时,用户账户处于未确认状态,而且用户的电子邮件地址和电话号码未经验证。

  4. 现在,应用程序会提示用户输入确认代码。用户无需立即输入代码。但是,用户只有在输入确认代码后才可登录。

  5. 用户在应用程序中输入确认代码。

  6. 应用程序调用 ConfirmSignUp 将代码发送到 Amazon Cognito 服务,该服务将验证代码并在代码正确时将用户账户设置为已确认状态。成功确认用户账户之后,Amazon Cognito 服务会自动将用于确认(电子邮件地址或电话号码)的属性标记为已验证。除非此属性的值发生更改,否则用户无需再次进行验证。

  7. 此时,用户账户处于已确认状态,用户可以登录。

在您要求用户确认电子邮件地址和电话号码的情况下

Amazon Cognito 在用户注册时仅验证一种联系方式。如果 Amazon Cognito 必须在验证电子邮件地址或电话号码之间进行选择,则会选择通过 SMS 消息发送验证码来验证电话号码。例如,如果您将用户池配置为允许用户验证电子邮件地址或电话号码,并且您的应用程序在注册时提供了这两个属性,则 Amazon Cognito 将仅验证电话号码。在用户验证其电话号码后,Amazon Cognito 会将用户的状态设置为 CONFIRMED,并允许用户登录您的应用程序。

在用户登录后,您的应用程序会提供相应选项来验证在注册期间未验证的联系方式。为了验证第二种联系方式,您的应用程序将调用 VerifyUserAttribute API 操作。请注意,此操作需要 AccessToken 参数,而 Amazon Cognito 只为经过身份验证的用户提供访问令牌。因此,您只能在用户登录后验证第二种联系方式。

如果您要求用户同时验证电子邮件地址和电话号码,请执行以下操作:

  1. 配置用户池以允许用户验证电子邮件地址或电话号码。

  2. 在应用程序的注册流程中,要求用户提供电子邮件地址和电话号码。调用 SignUp API 操作,并为 UserAttributes 参数提供电子邮件地址和电话号码。此时,Amazon Cognito 会向用户的手机发送一个验证码。

  3. 在应用程序界面中,会显示一个确认页面以供用户输入验证码。通过调用 ConfirmSignUp API 操作来确认用户。此时,用户的状态为 CONFIRMED,并且用户的电话号码已验证,但电子邮件地址未验证。

  4. 显示登录页,并通过调用 InitiateAuth API 操作对用户进行身份验证。对用户进行身份验证后,Amazon Cognito 将向您的应用程序返回访问令牌。

  5. 调用 GetUserAttributeVerificationCode API 操作。在请求中指定以下参数:

    • AccessToken – Amazon Cognito 在用户登录时返回的访问令牌。

    • AttributeName – 将 "email" 指定为属性值。

    Amazon Cognito 将向用户的电子邮件地址发送一个验证码。

  6. 显示一个确认页面以供用户输入验证码。当用户提交代码时,请调用 VerifyUserAttribute API 操作。在请求中指定以下参数:

    • AccessToken – Amazon Cognito 在用户登录时返回的访问令牌。

    • AttributeName – 将 "email" 指定为属性值。

    • Code – 用户提供的验证码。

    此时,电子邮件地址已验证。

允许用户在您的应用程序中注册但以用户池管理员身份进行确认

您可能不希望您的用户池自动在用户池中发送验证消息,但仍希望允许任何人注册账户。例如,该模型为人工审查新的注册请求以及批量验证和处理注册留出了空间。您可以在 Amazon Cognito 控制台中或使用经 IAM 身份验证的 API 操作 AdminConfirmSignUp 来确认新的用户账户。无论您的用户池是否发送验证消息,您都能以管理员身份确认用户账户。

您只能使用此方法确认用户的自助注册。要以管理员身份确认您创建的用户,请创建 AdminSetUserPassword API 请求并将 Permanent 设置为 True

  1. 用户通过输入用户名称、电话号码和/或电子邮件地址及其他可能属性,在您的应用程序中进行注册。

  2. Amazon Cognito 服务接收来自应用程序的注册请求。验证该请求包含注册所需的所有属性之后,该服务将完成注册过程,并向应用程序返回信息,表示注册已完成且正在等待确认。此时,用户账户处于未确认状态。账户经过确认后,用户才可登录。

  3. 确认用户的账户。您必须使用 Amazon 凭证登录 Amazon Web Services Management Console 或签署 API 请求才能确认账户。

    1. 要在 Amazon Cognito 控制台中确认用户,请导航到用户选项卡,选择要确认的用户,然后从操作菜单中选择确认

    2. 要在 Amazon API 或 CLI 中确认用户,请在 Amazon CLI 中创建 AdminConfirmSignUp API 请求或 admin-confirm-sign-up

  4. 此时,用户账户处于已确认状态,用户可以登录。

计算密钥哈希值

作为最佳实践,请将客户端密钥分配给您的机密应用程序客户端。当您向应用程序客户端分配客户端密钥时,您的 Amazon Cognito 用户池 API 请求必须包括一个哈希值,用于包含请求正文中的客户端密钥。为了验证您对以下列表中 API 操作的客户端密钥的了解,请将客户端密钥与应用程序客户端 ID 和用户的用户名连接起来,然后对该字符串进行 base64 编码。

应用程序将用户登录到具有密钥哈希值的客户端时,您可以使用任何用户池登录属性的值作为密钥哈希值的用户名元素。应用程序在使用 REFRESH_TOKEN_AUTH 的身份验证操作中请求新令牌时,用户名元素的值取决于您的登录属性。如果您的用户池没有将 username 用作登录属性,请通过用户的访问令牌或 ID 令牌中的 sub 声明设置密钥哈希用户名值。如果 username 为登录属性,请通过 username 声明设置密钥哈希用户名值。

以下 Amazon Cognito 用户池 API 接受 SecretHash 参数中的客户端密钥哈希值。

此外,以下 API 接受 SECRET_HASH 参数中的客户端密钥哈希值,这可以是在身份验证参数中或在质询响应中。

API 操作 SECRET_HASH 的父参数
InitiateAuth AuthParameters
AdminInitiateAuth AuthParameters
RespondToAuthChallenge ChallengeResponses
AdminRespondToAuthChallenge ChallengeResponses

密钥哈希值是 Base 64 编码的加密哈希消息身份验证代码(HMAC,Hash Message Authentication Code),使用用户池客户端的私有密钥、用户名以及消息中的客户端 ID 进行计算。以下伪代码显示如何计算此值。在此伪代码中,+ 表示串联,HMAC_SHA256 代表使用 HmacSHA256 生成 HMAC 值的函数,Base64 代表生成哈希输出的 Base-64 编码版本的函数。

Base64 ( HMAC_SHA256 ( "Client Secret Key", "Username" + "Client Id" ) )

有关如何计算和使用 SecretHash 参数的详细概述,请参阅 Amazon 知识中心内的如何解决 Amazon Cognito 用户池 API 中的“无法验证客户端 <client-id> 的密钥哈希”错误?

您可以在服务器端应用程序代码中使用以下代码示例:

Shell
echo -n "[username][app client ID]" | openssl dgst -sha256 -hmac [app client secret] -binary | openssl enc -base64
Java
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public static String calculateSecretHash(String userPoolClientId, String userPoolClientSecret, String userName) { final String HMAC_SHA256_ALGORITHM = "HmacSHA256"; SecretKeySpec signingKey = new SecretKeySpec( userPoolClientSecret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256_ALGORITHM); try { Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM); mac.init(signingKey); mac.update(userName.getBytes(StandardCharsets.UTF_8)); byte[] rawHmac = mac.doFinal(userPoolClientId.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(rawHmac); } catch (Exception e) { throw new RuntimeException("Error while calculating "); } }
Python
import sys import hmac, hashlib, base64 username = sys.argv[1] app_client_id = sys.argv[2] key = sys.argv[3] message = bytes(sys.argv[1]+sys.argv[2],'utf-8') key = bytes(sys.argv[3],'utf-8') secret_hash = base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode() print("SECRET HASH:",secret_hash)

无需验证电子邮件或电话号码即可确认用户账户

预注册 Lambda 触发器可用于在注册时自动确认用户账户,而无需提供确认码或者验证电子邮件或电话号码。通过此方法进行确认的用户可立即登录,而无需接收代码。

您还可通过此触发器将用户的电子邮件或电话号码标记为已验证。

注意

虽然这种方法对刚入门的用户而言很方便,但我们建议至少自动验证电子邮件或电话号码之一。否则,如果用户忘记密码,可能就无法进行恢复。

如果您不要求用户在注册时接收并输入确认码,也不在预注册 Lambda 触发器中自动验证电子邮件和电话号码,则您将承担对于该用户账户不具备经验证的电子邮件地址或电话号码的风险。用户可以稍后验证电子邮件地址或电话号码。但是,如果用户忘记自己的密码且没有经验证的电子邮件地址或电话号码,则用户将被锁定而无法使用账户,因为忘记密码流程需要经验证的电子邮件或电话号码以便向用户发送验证码。

当用户更改其电子邮件或电话号码时应进行验证

当用户在应用程序中更新其电子邮件地址或电话号码时,如果您将用户池配置为自动验证该属性,Amazon Cognito 会立即向用户发送带有验证码的消息。然后,用户必须将验证消息中的代码提供给您的应用程序。然后,您的应用程序在 VerifyUserAttribute API 请求中提交代码,以完成对新属性值的验证。

如果用户池不要求用户验证更新的电子邮件地址或电话号码,Amazon Cognito 会立即更改更新的 email phone_number 属性的值,并将该属性标记为未验证。您的用户无法使用未经验证的电子邮件或电话号码登录。他们必须先完成对更新值的验证,然后才能将该属性用作登录别名。

如果您的用户池要求用户验证更新的电子邮件地址或电话号码,则 Amazon Cognito 会将属性保持为已验证状态并设置为其原始值,直到您的用户验证新属性值为止。如果属性是登录的别名,您的用户可以使用原始属性值登录,直到验证过程将属性更改为新值。有关如何配置用户池以要求用户验证更新的属性的更多信息,请参阅配置电子邮件或电话验证

您可以使用自定义消息 Lambda 触发器自定义验证消息。有关更多信息,请参阅 自定义消息 Lambda 触发器。当用户的电子邮件地址或电话号码未经验证时,您的应用程序应通知用户必须验证该属性,并为用户提供一个按钮或链接以验证其新的电子邮件地址或电话号码。

针对由管理员或开发人员创建的用户账户的确认和验证过程

由管理员或开发人员创建的用户账户已经处于已确认状态,所以用户无需输入确认代码。Amazon Cognito 服务向这些用户发送的邀请消息包含用户名和临时密码。用户需要在登录前更改密码。有关更多信息,请参阅自定义电子邮件和 SMS 消息中的 以管理员身份创建用户账户使用 Lambda 触发器自定义用户池工作流中的自定义消息触发器。

针对导入的用户账户的确认和验证过程

使用 Amazon Web Services Management Console、CLI 或 API 中的用户导入功能创建的用户账户(请参阅通过 CSV 文件将用户导入用户池中)已处于已确认状态,因此用户无需输入确认代码。没有发送邀请消息。但是,导入的用户账户要求用户首先调用 ForgotPassword API 来请求代码,然后通过调用 ConfirmForgotPassword API 来使用发送的代码创建密码,之后方可登录。有关更多信息,请参阅 要求导入的用户重置密码

导入用户账户时,用户的电子邮件或电话号码必须已标记为已验证,从而用户无需验证即可登录。

在测试应用程序时发送电子邮件

当用户在您的用户池的客户端应用程序中创建和管理其账户时,Amazon Cognito 将向用户发送电子邮件。如果您将用户池配置为要求电子邮件验证,Amazon Cognito 将在以下情况下发送电子邮件:

  • 用户注册。

  • 用户更新其电子邮件地址。

  • 用户执行一项调用 ForgotPassword API 操作的操作。

  • 您以管理员身份创建用户账户。

根据发起电子邮件递送的操作,电子邮件将包含验证码或临时密码。您的用户必须接收这些电子邮件并理解消息。否则,他们可能无法登录并使用您的应用程序。

要确保电子邮件成功发送并且邮件看起来正确,请测试应用程序中从 Amazon Cognito 启动电子邮件传送的操作。例如,通过使用应用程序中的注册页面或通过使用 SignUp API 操作,您可以通过使用测试电子邮件地址进行注册来启动电子邮件传送。在通过此方式进行测试时,请记住以下几点:

重要提示

当您使用电子邮件地址测试从 Amazon Cognito 启动电子邮件传送的操作时,请勿使用虚假的电子邮件地址(没有邮箱的电子邮件地址)。使用真实的电子邮件地址才能接收来自 Amazon Cognito 的电子邮件,而不会创建查无此人的邮件

在 Amazon Cognito 未能将电子邮件传送到收件人邮箱时会产生查无此人的邮件,如果邮箱不存在,则始终会发生这种情况。

Amazon Cognito 会限制持续产生查无此人的邮件的Amazon账户可发送的电子邮件数量。

当您测试启动电子邮件传送的操作时,请使用下列电子邮件地址之一以防止出现查无此人的邮件:

  • 您拥有的用于测试的电子邮件账户的地址。当您使用自己的电子邮件地址时,您将收到 Amazon Cognito 发送的电子邮件。利用此电子邮件,您可以使用验证码来测试应用程序中的注册体验。如果您为用户池自定义了电子邮件,则可检查自定义项看起来是否正确。

  • 邮箱模拟器地址:success@simulator.amazonses.com。如果您使用模拟器地址,Amazon Cognito 将成功发送电子邮件,但您无法查看。当您不需要使用验证码并且不需要检查电子邮件时,此选项很有用。

  • 添加了任意标签的邮箱模拟器地址(如 success+user1@simulator.amazonses.comsuccess+user2@simulator.amazonses.com)。Amazon Cognito 可成功向这些地址发送电子邮件,但您无法查看其发送的电子邮件。当您希望通过向用户池添加多个测试用户来测试注册过程,并且每个测试用户都具有一个唯一的电子邮件地址时,此选项很有用。