配置多重身份验证

本页介绍了如何配置多重身份验证 (MFA),以便通过电子邮件发送验证码来验证用户的身份。借助此功能,您可以验证用户是否拥有与其账号关联的电子邮件地址。MFA 有助于保护您的用户免受凭据填充攻击和账号盗用 (ATO) 攻击。

MFA 仅适用于基于得分的网站密钥,不适用于复选框网站密钥。

了解 MFA 的配置过程

reCAPTCHA 的多重身份验证功能是在常规 reCAPTCHA 工作流上实现的。

概括来讲,MFA 工作流程如下:

  1. 检测您网站上的关键工作流
  2. 使用 execute() 调用返回的令牌和 MFA 参数获取 MFA requestToken,以创建评估
  3. 根据您要使用的渠道(仅支持电子邮件),使用 requestToken 触发 MFA 质询
  4. 在您的网站上验证最终用户输入的 PIN 码
  5. 使用验证请求中返回的令牌创建新的评估

准备工作

  1. 为 reCAPTCHA 准备环境

  2. 在您向项目添加结算账号后,系统会启动安全审核,审核完成后,您就可以使用多重身份验证。添加结算账号,在您的网站上启用此功能。

  3. 如果您想启用 MFA 的电子邮件验证功能,请执行以下操作:

    1. 在 Google Cloud 控制台中,前往 reCAPTCHA 页面。

      前往 reCAPTCHA

    2. 验证项目名称是否显示在资源选择器中。

      如果您没有看到项目名称,请点击资源选择器,然后选择您的项目。

    3. 点击 设置

    4. 多重身份验证窗格中,点击配置

    5. 配置多重身份验证对话框中,执行以下操作:

      1. 如需启用电子邮件验证,请点击启用电子邮件切换开关。
      2. 发件人姓名框中,输入您的姓名。
      3. 发件人电子邮件地址框中,输入您的电子邮件地址。

    6. 点击保存

  4. 使用基于得分的密钥在您的网站上设置 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 密钥。

    客户端库

    使用以下资源:

  • 选择一个稳定的账号标识符 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 账号保护程序,除了与多重身份验证相关的信息之外,评估响应还会包含与账号保护程序相关的信息。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 质询,请执行以下操作:

  1. 测试多重身份验证 (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 变量会传递给包含判定令牌的链式函数,以便通过在后端创建的评估进行验证。

  2. 使用以下参数创建验证句柄并发起质询:

    // 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
  }
);

创建新评估

使用 accountIdendpoints 创建新的评估。如需了解相关说明,请参阅为多重身份验证创建评估

在客户端完成工作流后,您将获得一个新令牌,可以用来获取触发的验证结果。此评估包含有关最新成功验证的最近时间戳,以及成功结果状态。

以下示例显示了一个使用从网站获得的新令牌创建新评估时收到的示例评估:

{
  [...],
  "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 没有与最新验证相关的信息(从未验证)。

后续步骤