配置多重身份验证

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

MFA 适用于基于得分的键,但不适用于复选框键。

了解 MFA 的配置流程

reCAPTCHA Enterprise 的 MFA 功能在常规 reCAPTCHA Enterprise 工作流之上实现。

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

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

准备工作

  1. 为 reCAPTCHA Enterprise 准备好环境

  2. 通过安全审核后,您可以访问 MFA。请与我们的销售团队联系,为您的网站配置此功能。请向销售团队提供以下新手入门信息:

    • Google Cloud 项目编号
    • 初始配置 reCAPTCHA 密钥
    • 平均 QPS(每秒电子邮件数)
    • QPS 峰值(每秒电子邮件数)
    • 对于电子邮件 MFA,请提供测试期间的发件人地址以及电子邮件地址或网域
  3. 如果要启用 MFA 的电子邮件验证功能,请执行以下操作:

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

      转到 reCAPTCHA Enterprise

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

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

    3. 点击 设置

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

    5. Configure MFA 对话框中,执行以下操作:

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

    6. 点击保存

  4. 使用基于得分的密钥在您的网站上设置 reCAPTCHA Enterprise

对您网站上的关键工作流进行插桩处理

通过 execute() 函数将必要的信息传递给 reCAPTCHA Enterprise,以用于风险评估。execute() 函数返回生成令牌时解析的 promise。

execute() 函数附加另一个 twofactor 参数,如以下示例代码所示:

  grecaptcha.enterprise.execute(KEY_ID, {
    action: 'login',
    twofactor: true
  }).then(token => {
    // Handle the generated token.
  });

KEY_ID 替换为您为网站创建的基于得分的密钥。

创建评估

使用 execute() 函数生成的令牌,通过后端中的 reCAPTCHA Enterprise 客户端库或 REST API 创建评估。

本文档介绍了如何使用 REST API 为 MFA 创建评估。 如需了解如何使用客户端库创建评估,请参阅为网站创建评估

在创建评估之前,请执行以下操作:

  • 设置向 reCAPTCHA Enterprise 进行的身份验证。

    您选择的身份验证方法取决于设置 reCAPTCHA Enterprise 的环境。下表可帮助您选择适当的身份验证方法和受支持的接口来设置身份验证:

    环境 接口 身份验证方法
    Google Cloud
    • REST
    • 客户端库
    使用关联的服务帐号
    本地或其他云服务提供商 REST 使用 API 密钥工作负载身份联合

    如果您想要使用 API 密钥,我们建议您通过应用 API 密钥限制来保护 API 密钥。

    客户端库

    使用以下资源:

  • 选择不常由用户更改的稳定帐号标识符 accountId,并通过 projects.assessments.create 方法将其提供给评估。对于与同一用户相关的所有事件,这个稳定的帐号标识符应具有相同的值。您可以提供以下内容作为帐号标识符:

    用户标识符

    如果每个帐号都可以与稳定的用户名、电子邮件地址或手机号码唯一关联,您可以将其用作 accountId。在您提供此类跨网站标识符(可跨网站重复使用的标识符)后,reCAPTCHA Enterprise 会使用这些信息,根据跨网站模型,标记存在滥用行为的帐号标识符,并掌握与这些标识符相关的跨网站滥用模式信息,从而提升对用户帐号的保护力度。

    或者,如果您有一个与每个帐号唯一关联的内部用户 ID,则可以将其作为 accountId 提供。

    经过哈希处理或加密

    如果您没有与每个帐号唯一关联的内部用户 ID,则可以将任何稳定的标识符转换为不透明的网站专用帐号标识符。reCAPTCHA Enterprise 账号卫士仍然需要此标识符,才能了解用户活动模式并检测异常行为,但此标识符不会与其他网站共享。

    选择任意稳定的账号标识符并将其设为不透明,然后使用加密或哈希处理方法将其发送到 reCAPTCHA Enterprise:

    • 加密(推荐):使用可生成稳定密文的确定性加密方法对帐号标识符进行加密。如需了解详细说明,请参阅确定性地加密数据。当您选择对称加密而非哈希时,无需保留用户标识符与相应不透明用户标识符之间的映射。解密 reCAPTCHA Enterprise 返回的不透明标识符,以将其转换为用户标识符。

    • 哈希处理:建议您使用 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 Enterprise 帐号卫士,则评估响应除了包含与 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 质询,请执行以下操作:

  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 创建新的评估。如需了解相关说明,请参阅为 MFA 创建评估

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

以下示例展示了您在使用从网站获取的新令牌创建新评估时收到的评估示例:

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

后续步骤