本页介绍了如何配置多重身份验证 (MFA),以便通过电子邮件发送验证码来验证用户的身份。使用此功能,您可以验证用户是否拥有与其账号关联的电子邮件地址。MFA 有助于保护您的用户免受凭据填充攻击和账号盗用 (ATO) 攻击。
MFA 仅适用于基于得分的密钥,不适用于复选框密钥。
了解 MFA 的配置过程
reCAPTCHA 的 MFA 功能是在常规 reCAPTCHA 工作流程的基础上实现的。
从总体上讲,MFA 工作流程如下:
- 检测网站上的关键工作流。
- 使用 execute()调用返回的令牌和 MFA 参数创建评估,以获取 MFArequestToken。
- 根据您要使用的渠道(仅支持电子邮件),使用 requestToken触发 MFA 挑战。
- 验证最终用户在您的网站上输入的 PIN 码。
- 使用验证请求中返回的令牌创建新的评估。
准备工作
- 添加结算账号后,系统会启动安全审核,审核通过后即可使用 MFA。 添加结算账号,在您的网站上启用此功能。 
- 如果您想启用 MFA 的电子邮件验证功能,请执行以下操作: - 在 Google Cloud 控制台中,前往 reCAPTCHA 页面。 
- 验证项目名称是否显示在资源选择器中。 - 如果您没有看到项目名称,请点击资源选择器,然后选择您的项目。 
- 点击 设置。 
- 在多重身份验证窗格中,点击配置。 
- 在配置多重身份验证对话框中,执行以下操作: - 如需启用电子邮件验证,请点击启用电子邮件切换开关。
- 在发件人名称框中,输入您的名称。
- 在发件人电子邮件框中,输入您的电子邮件地址。  
 
- 点击保存。 
 
检测网站上的关键工作流
通过 execute() 函数将必要的信息传递给 reCAPTCHA,以用于风险评估。execute() 函数返回生成令牌时解析的 promise。
向 execute() 函数附加另一个 twofactor 参数,如以下示例代码所示:
  grecaptcha.enterprise.execute(KEY_ID, {
    action: 'login',
    twofactor: true
  }).then(token => {
    // Handle the generated token.
  });
将 KEY_ID 替换为您为网站创建的基于得分的密钥。
创建评估
借助通过 execute() 函数生成的令牌,使用 reCAPTCHA 客户端库或 REST API 从后端创建评估。
本文档介绍了如何使用 REST API 为 MFA 创建评估。 如需了解如何使用客户端库创建评估,请参阅为网站创建评估。
在创建评估之前,请执行以下操作:
- 设置向 reCAPTCHA 进行身份验证。 - 您选择的身份验证方法取决于 reCAPTCHA 的设置环境。下表可帮助您选择合适的身份验证方法和支持的接口来设置身份验证: - 环境 - 接口 - 身份验证方法 - Google Cloud - REST
- 客户端库
 - 使用关联的服务账号。 - 本地或其他云服务提供商 - REST - 使用 API 密钥或工作负载身份联合。 - 如果您想使用 API 密钥,建议您通过应用 API 密钥限制来保护 API 密钥。 - 客户端库 - 使用以下资源: - 对于 Python 或 Java,请使用 API 密钥或工作负载身份联合。
						如果您想使用 API 密钥,建议您通过应用 API 密钥限制来保护 API 密钥。 
- 如需查看其他语言的版本,请参阅工作负载身份联合。
 
- 选择一个用户不会经常更改的稳定账号标识符 - accountId,并通过- projects.assessments.create方法将其提供给评估。对于与同一用户相关的所有事件,此稳定的账号标识符应具有相同的值。您可以提供以下信息作为账号标识符:- 用户标识符- 如果每个账号都可以与稳定的用户名、电子邮件地址或手机号码唯一关联,则可以使用它作为 - accountId。当您提供此类跨网站标识符(可在多个网站上重复使用的标识符)时,reCAPTCHA 会使用这些信息,通过标记滥用账号标识符并利用与这些标识符相关的跨网站滥用模式知识,基于跨网站模型来改进对用户账号的保护。- 或者,如果您有与每个账号唯一关联的内部用户 ID,则可以将其作为 - accountId提供。- 经过哈希处理或加密- 如果您没有与每个账号唯一关联的内部用户 ID,则可以将任何稳定的标识符转换为不透明的网站专用账号标识符。reCAPTCHA 账号卫士仍需要此标识符来了解用户活动模式并检测异常行为,但此标识符不会与其他网站共享。 - 选择任意稳定的账号标识符,并使用加密或哈希处理使其不透明,然后再将其发送给 reCAPTCHA: - 加密(推荐):使用确定性加密方法对账号标识符进行加密,以生成稳定的密文。如需查看详细说明,请参阅确定性地加密数据。如果您选择对称加密而非哈希处理,则无需保留用户标识符与相应不透明用户标识符之间的映射关系。 对 reCAPTCHA 返回的不透明标识符进行解密,以将其转换为用户标识符。 
- 哈希处理:我们建议使用 SHA256-HMAC 方法和您选择的自定义随机数对账号标识符进行哈希处理。由于哈希是单向的,因此您需要保留生成的哈希与用户标识符之间的映射,以便将返回的哈希处理后的账号标识符映射回原始账号。 
 
在 projects.assessments.create 方法中,添加 accountId 参数以及一个端点(例如电子邮件地址),以便在评估中进行验证。
在使用任何请求数据之前,请先进行以下替换:
- PROJECT_ID:您的 Google Cloud 项目 ID。
- TOKEN:从 grecaptcha.enterprise.execute()调用返回的令牌。
- KEY_ID:您在网站上安装的基于得分的密钥。
- ACCOUNT_ID:您网站上用户账号的唯一标识符。
- EMAIL_ID:需要触发验证请求的电子邮件地址。
HTTP 方法和网址:
POST https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments
请求 JSON 正文:
{
  "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "userInfo": {
       "accountId": "ACCOUNT_ID"
    }
  }
  "accountVerification": {
    "endpoints": [{
      "emailAddress": "EMAIL_ID",
    }]
  }
}
如需发送请求,请选择以下方式之一:
curl
      将请求正文保存在名为 request.json 的文件中,然后执行以下命令:
    
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments"
PowerShell
      将请求正文保存在名为 request.json 的文件中,然后执行以下命令:
    
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments" | Select-Object -Expand Content
您应该收到类似以下内容的 JSON 响应:
{
  [...],
  "accountVerification": {
    "endpoints": [{
      "emailAddress": "foo@bar.com",
      "requestToken": "tplIUFvvJUIpLaOH0hIVj2H71t5Z9mDK2RhB1SAGSIUOgOIsBv",
      "lastVerificationTime": "",
    }],
    "latestVerificationResult": "RESULT_UNSPECIFIED"
  }
}
评估将包括设备上发布令牌的给定端点最近一次成功验证的日期和时间(如果有的话)。它还为每个端点包含一个 requestToken 字段,其中包含一个加密字符串。如果您决定触发该端点的 MFA 挑战,则必须将此加密的字符串发送回网页。请求令牌的有效期为 15 分钟。
推荐操作
如果您已为项目启用 reCAPTCHA 账号保护程序,则评估响应除了包含与 MFA 相关的信息外,还包含与账号保护程序相关的信息。recommended_action 字段显示了在触发 MFA 质询之前可以采取的操作。
以下示例展示了一项示例评估,其中将跳过 MFA 作为建议的操作:
{ [...], "accountDefenderAssessment": { labels: ["PROFILE_MATCH"], "recommended_action": "SKIP_2FA" } }
recommended_action 字段可以具有以下任意值:
| 值 | 说明 | 
|---|---|
| RECOMMENDED_ACTION_UNSPECIFIED | 表示账号保护功能无法对此请求做出判断。 | 
| SKIP_2FA | 表示账号保护程序认为可以安全地跳过此评估的 MFA。这通常意味着用户最近已在此设备上通过您网站的验证。 | 
| REQUEST_2FA | 表示您为用户触发了 MFA 挑战。如需了解详情,请参阅账号保护工具评估响应。 | 
在您的网站上触发 MFA 挑战
如需根据评估中所包含的信息来挑战用户,请将您要验证的端点的 MFA requestToken 从评估发送回网页。
调用 challengeAccount() 来触发 MFA 挑战。challengeAccount() 函数返回一个在挑战完成后被解析或在出现错误或超时时被拒绝的 promise。完成后,系统会生成包含更新信息的新令牌,然后发送该令牌进行评估。
如需触发 MFA 质询,请执行以下操作:
- 测试 MFA 集成。 - 通过调用 - challengeAccount()并提供以下值来触发 MFA 挑战:- KEY_ID:您在网站上安装的基于得分的密钥。
- REQUEST_TOKEN_FROM_ASSESSMENT:评估响应中的 requestToken字段的值。
- CONTAINER_HTML_COMPONENT_ID:必须在其中呈现验证挑战的 HTML 组件的 ID。 如果您未指定此参数,则挑战会呈现在页面顶部的叠加层中。
 - 以下示例展示了如何通过调用 - challengeAccount()来触发 MFA 挑战:- grecaptcha.enterprise.challengeAccount(KEY_ID, { 'account-token': REQUEST_TOKEN_FROM_ASSESSMENT, 'container': CONTAINER_HTML_COMPONENT_ID }).then(newToken => { // Handle the new token. });- 如果 - challengeAccount()请求成功,系统会显示 HTML 组件,以便您输入收到的 PIN 码。输入正确的 PIN 后,- newToken变量会传递给包含判决令牌的链式函数,该令牌将通过在后端创建的评估进行验证。
- 创建验证句柄并使用以下参数发起质询: - // Initialize verification handle. const verificationHandle = grecaptcha.enterprise.eap.initTwoFactorVerificationHandle( KEY_ID, REQUEST_TOKEN_FROM_ASSESSMENT ); // Call the challenge API. verificationHandle.challengeAccount().then( (challengeResponse) => { if (challengeResponse.isSuccess()) { // Handle success: This means displaying an input for the end user to // enter the PIN that they received and then call the `verifyAccount(pin)` // method. } else { // Handle API failure } });
通过网页验证 MFA 代码
从最终用户那里获得 PIN 后,您必须验证该 PIN 是否正确。
如需验证 PIN 码,请使用最终用户输入的 PIN 码调用 verificationHandle.verifyAccount()。
verificationHandle.verifyAccount(pin).then(
  (verifyResponse) => {
    if (verifyResponse.isSuccess()) {
      // Handle success: Send the result of `verifyResponse.getVerdictToken()`
      // to the backend in order to determine if the code was valid.
    } else {
      // Handle API failure
    }
  },
  (error) => {
    // Handle other errors
  }
);
创建新评估
使用 accountId 和 endpoints 创建新的评估。如需查看相关说明,请参阅为多重身份验证创建评估。
在客户端完成工作流后,您将获得一个新令牌,可以用来获取触发的验证结果。此评估包含有关最新成功验证的最近时间戳,以及成功结果状态。
以下示例显示了一个使用从网站获得的新令牌创建新评估时收到的示例评估:
{ [...], "accountVerification": { "endpoints": [{ "emailAddress": "foo@bar.com", "requestToken": "tplIUFvvJUIpLaOH0hIVj2H71t5Z9mDK2RhB1SAGSIUOgOIsBv", "lastVerificationTime": "2020-03-23 08:27:12 PST", }], "latestVerificationResult": "SUCCESS_USER_VERIFIED" } }
latestVerificationResult 字段可以显示如下表中列出的不同的状态:
| 验证结果状态 | 说明 | 
|---|---|
| SUCCESS_USER_VERIFIED | 已成功验证用户。 | 
| ERROR_USER_NOT_VERIFIED | 用户未通过验证挑战。 | 
| ERROR_SITE_ONBOARDING_INCOMPLETE | 您的网站未正确配置,因此无法使用此功能。 | 
| ERROR_RECIPIENT_NOT_ALLOWED | 此收件人未获准向其发送电子邮件(仅在测试期间)。 | 
| ERROR_RECIPIENT_ABUSE_LIMIT_EXHAUSTED | 此收件人短时间内收到了过多的验证码。 | 
| ERROR_CUSTOMER_QUOTA_EXHAUSTED | 您已超出可用的 MFA 配额。 | 
| ERROR_CRITICAL_INTERNAL | 由于我们的系统出现内部错误,因此未完成验证。 | 
| RESULT_UNSPECIFIED | 没有与最新验证相关的信息(从未验证)。 |