检测并防范移动应用中的与账号相关的欺诈活动

本文档介绍了如何使用 reCAPTCHA 账号卫士在移动应用中检测和防范与账号相关的欺诈活动。

reCAPTCHA 可帮助您保护关键操作,例如登录和结账。不过,多种微妙形式的账号滥用可能会造成 通过在一定时间范围内观察特定用户在移动应用上的行为来检测 。reCAPTCHA 账号卫士可帮助识别这些类型 通过为移动应用创建专门针对网站的模型来检测 可疑行为趋势或活动变化。通过使用特定于网站的模型,reCAPTCHA 账号卫士可帮助您检测以下内容:

  • 可疑活动
  • 具有类似行为的账号
  • 来自为特定用户标记为可信的设备的请求

根据 reCAPTCHA 账号卫士的分析和特定于网站的模型,您可以执行以下操作:

  • 限制或停用欺诈性账号。
  • 防止账号盗用尝试。
  • 减少成功的账号盗用。
  • 请仅授予对来自正当用户账号的请求的访问权限。
  • 减少用户通过其信任的设备登录时的不便。

准备工作

  1. 向项目添加结算账号后,系统会触发自动安全审核,审核完成后,您就可以使用适用于移动应用的 reCAPTCHA 账号保护程序了。 添加结算账号 添加到项目中,为您的网站添加此功能。
  2. 为 reCAPTCHA 准备环境
  3. 创建基于得分的键

为您的移动应用配置 reCAPTCHA 账号卫士

reCAPTCHA 账号卫士需要全面了解账号活动,才能有效检测。如需开始向 reCAPTCHA 账号卫士提交与账号相关的活动,以及创建和改进特定于您网站的模型,请执行以下操作:

  1. 将 reCAPTCHA 与您的移动应用集成。

  2. 报告关键用户操作
  3. 评估关键用户事件
  4. 为用户事件添加注释以调整网站专用模型

报告关键用户操作

为了检测可疑活动模式并更好地了解您网站上的典型活动模式,reCAPTCHA 账号防护工具需要关键用户操作的相关信息。 对于应用中使用 reCAPTCHA 保护的每项操作,请使用 RecaptchaAction 调用 execute() 方法。如需详细了解 execute()RecaptchaAction,请参阅以下内容:

reCAPTCHA 提供了一组内置操作,您也可以根据需要创建自定义操作。

下表列出了在报告关键用户操作时可以使用的操作名称。

操作名称 用户发起的事件或用户操作
LOGIN

登录移动应用。

SIGNUP

在移动应用上注册。

评估关键用户事件

当您对用户操作调用 execute() 时,它会生成令牌。对于关键用户事件(例如登录成功和失败、注册以及已登录用户的操作),请创建评估来评估 execute() 调用的结果。该评估会提供风险判定结果,以便您据此决定如何处理可能存在欺诈行为的活动。您可以采取的一些措施包括屏蔽可疑请求、质疑有风险的登录行为,以及调查感兴趣的账号。

reCAPTCHA 账号卫士要求您提供一个稳定的账号标识符,以便 将用户活动(如登录请求、登录请求和注册请求)归功于 特定账号。这有助于 reCAPTCHA 账号卫士了解用户活动模式,并为每个账号构建活动模型,以便更好地检测异常流量和滥用流量。

选择一个稳定的账号标识符 accountId(用户不经常更改),并在 projects.assessments.create 方法中将其提供给评估。这个稳定的账号标识符应该包含 与同一用户相关的所有事件都使用相同的值。您可以提供以下内容作为账号 标识符:

用户标识符

是否每个账号都可以与固定的用户名、电子邮件地址或手机号码相关联 编号,您可以将其用作 accountId。当您提供此类跨网站标识符(可在多个网站中重复使用的标识符)时,reCAPTCHA 会使用这些信息,通过标记滥用账号标识符并利用与这些标识符相关的跨网站滥用行为模式知识,根据跨网站模型加强对用户账号的保护。

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

经过哈希处理或加密

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

请选择任何稳定的账号标识符并将其设为不透明,然后再发送到 reCAPTCHA,具体方法是: 加密或哈希处理:

  • 加密(推荐):使用确定性对账号标识符进行加密 这种加密方法可生成稳定的密文。有关详细说明,请参阅 加密数据 确定性地。如果选择对称加密而非哈希 在您的用户标识符和对应的不透明用户标识符之间保持映射。 解密 reCAPTCHA 返回的不透明标识符,以将其转换为 用户标识符。

  • 哈希方法:我们建议使用 SHA256-HMAC 方法对账号标识符进行哈希处理 自选盐由于哈希值是单向的,因此您需要在生成的哈希值和用户标识符之间保持映射,以便将返回的经过哈希处理的账号标识符映射回原始账号。

除了为所有与账号相关的请求提供稳定的账号标识符外,您还可以为某些特定请求提供其他账号标识符(可能不稳定)。 除 accountId 帮助之外,还提供特定于上下文的账号标识符 reCAPTCHA 账号卫士能更好地理解用户活动并检测账号 包版会试图确保您的用户账号安全无虞。如果您提供额外的标识符 reCAPTCHA 会根据以下信息来更好地保护您的用户账号: 举报存在滥用行为的账号标识符并利用对跨网站滥用行为的了解,构建跨网站模型 与这些标识符相关的模式。例如,您可以提供以下信息:

  • 用作登录标识名的用户名、电子邮件地址或手机号码 请求

  • 已通过多重身份验证的电子邮件地址或手机号码 身份验证请求

  • 用户在请求更新账号时提供的电子邮件地址或电话号码(主号码或辅助号码)

  • 用户在注册期间提供的电子邮件地址和手机号码 请求

对于所有与账号相关的请求,将所选的稳定账号标识符附加到 projects.assessments.create 方法中的 accountId 参数。(可选) 使用 userIds 为相关请求提供额外的账号标识符 字段。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID
  • TOKEN:从 execute() 调用返回的令牌
  • KEY_ID:与应用关联的 reCAPTCHA 密钥
  • ACCOUNT_ID:与 用户账号
  • EMAIL_ADDRESS:可选。与此请求关联的电子邮件地址(如果有)
  • PHONE_NUMBER:可选。与此请求关联的手机号码(如果 任意
  • USERNAME:可选。与此请求关联的用户名(如果有)

HTTP 方法和网址:

POST https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments

请求 JSON 正文:

{
  "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "userInfo": {
      "accountId": "ACCOUNT_ID",
      "userIds": [
        {
          "email": "EMAIL_ADDRESS"
        },
        {
          "phoneNumber": "PHONE_NUMBER"
        },
        {
          "username": "USERNAME"
        }
      ]
    }
  }
}

如需发送请求,请选择以下方式之一:

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 响应:

{
  "tokenProperties": {
    "valid": true,
    "androidPackageName": "com.example.app" or "iosBundleId": "com.example.app",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY",
    "userInfo": {
      "accountId": "ACCOUNT_ID"
    }
  },
  "name": "projects/PROJECT_NUMBER/assessments/b6ac310000000000",
  "accountDefenderAssessment": {
    "labels": ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

代码示例

Java

如需向 reCAPTCHA 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AccountDefenderAssessment.AccountDefenderLabel;
import com.google.recaptchaenterprise.v1.Assessment;
import com.google.recaptchaenterprise.v1.CreateAssessmentRequest;
import com.google.recaptchaenterprise.v1.Event;
import com.google.recaptchaenterprise.v1.ProjectName;
import com.google.recaptchaenterprise.v1.RiskAnalysis.ClassificationReason;
import com.google.recaptchaenterprise.v1.TokenProperties;
import com.google.recaptchaenterprise.v1.UserId;
import com.google.recaptchaenterprise.v1.UserInfo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class AccountDefenderAssessment {

  public static void main(String[] args)
      throws IOException, NoSuchAlgorithmException, InvalidKeyException {
    // TODO(developer): Replace these variables before running the sample.
    // projectId: Google Cloud Project ID
    String projectId = "project-id";

    // recaptchaSiteKey: Site key obtained by registering a domain/app to use recaptcha
    // services.
    String recaptchaSiteKey = "recaptcha-site-key";

    // token: The token obtained from the client on passing the recaptchaSiteKey.
    // To get the token, integrate the recaptchaSiteKey with frontend. See,
    // https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#frontend_integration_score
    String token = "recaptcha-token";

    // recaptchaAction: The action name corresponding to the token.
    String recaptchaAction = "recaptcha-action";

    // Unique ID of the user, such as email, customer ID, etc.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    // User phone number
    String phoneNumber = "555-987-XXXX";

    // User email address
    String emailAddress = "john.doe@example.com";

    accountDefenderAssessment(projectId, recaptchaSiteKey, token, recaptchaAction, accountId, phoneNumber, emailAddress);
  }

  /**
   * This assessment detects account takeovers. See,
   * https://cloud.google.com/recaptcha-enterprise/docs/account-takeovers The input is the hashed
   * account id. Result tells if the action represents an account takeover. You can optionally
   * trigger a Multi-Factor Authentication based on the result.
   */
  public static void accountDefenderAssessment(
      String projectId,
      String recaptchaSiteKey,
      String token,
      String recaptchaAction,
      String accountId,
      String phoneNumber,
      String emailAddress)
      throws IOException {
    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

      // Set the properties of the event to be tracked.
      Event.Builder eventBuilder =
          Event.newBuilder()
              .setSiteKey(recaptchaSiteKey)
              .setToken(token);

      // Set the account id, email address and phone number (of the user).
      eventBuilder.setUserInfo(
        UserInfo.newBuilder()
          .setAccountId(accountId)
          .addUserIds(UserId.newBuilder().setEmail(emailAddress))
          .addUserIds(UserId.newBuilder().setPhoneNumber(phoneNumber)));

      Event event = eventBuilder.build();

      // Build the assessment request.
      CreateAssessmentRequest createAssessmentRequest =
          CreateAssessmentRequest.newBuilder()
              .setParent(ProjectName.of(projectId).toString())
              .setAssessment(Assessment.newBuilder().setEvent(event).build())
              .build();

      Assessment response = client.createAssessment(createAssessmentRequest);

      // Check integrity of the response token.
      if (!checkTokenIntegrity(response.getTokenProperties(), recaptchaAction)) {
        return;
      }

      // Get the reason(s) and the reCAPTCHA risk score.
      // For more information on interpreting the assessment,
      // see: https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
      for (ClassificationReason reason : response.getRiskAnalysis().getReasonsList()) {
        System.out.println(reason);
      }
      float recaptchaScore = response.getRiskAnalysis().getScore();
      System.out.println("The reCAPTCHA score is: " + recaptchaScore);
      String assessmentName = response.getName();
      System.out.println(
          "Assessment name: " + assessmentName.substring(assessmentName.lastIndexOf("/") + 1));

      // Get the Account Defender result.
      com.google.recaptchaenterprise.v1.AccountDefenderAssessment accountDefenderAssessment =
          response.getAccountDefenderAssessment();
      System.out.println(accountDefenderAssessment);

      // Get Account Defender label.
      List<AccountDefenderLabel> defenderResult =
          response.getAccountDefenderAssessment().getLabelsList();
      // Based on the result, can you choose next steps.
      // If the 'defenderResult' field is empty, it indicates that Account Defender did not have
      // anything to add to the score.
      // Few result labels: ACCOUNT_DEFENDER_LABEL_UNSPECIFIED, PROFILE_MATCH,
      // SUSPICIOUS_LOGIN_ACTIVITY, SUSPICIOUS_ACCOUNT_CREATION, RELATED_ACCOUNTS_NUMBER_HIGH.
      // For more information on interpreting the assessment, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/account-defender#interpret-assessment-details
      System.out.println("Account Defender Assessment Result: " + defenderResult);
    }
  }

  private static boolean checkTokenIntegrity(
      TokenProperties tokenProperties, String recaptchaAction) {
    // Check if the token is valid.
    if (!tokenProperties.getValid()) {
      System.out.println(
          "The Account Defender Assessment call failed because the token was: "
              + tokenProperties.getInvalidReason().name());
      return false;
    }

    // Check if the expected action was executed.
    if (!tokenProperties.getAction().equals(recaptchaAction)) {
      System.out.printf(
          "The action attribute in the reCAPTCHA tag '%s' does not match "
              + "the action '%s' you are expecting to score",
          tokenProperties.getAction(), recaptchaAction);
      return false;
    }
    return true;
  }
}

解读关键用户事件的风险判定结果

如果您在启用账号保护程序的情况下创建评估,账号保护程序 返回 accountDefenderAssessment 作为评估响应的一部分。 accountDefenderAssessment 的值可帮助您评估用户活动是合法还是欺诈。它还会返回 为用户事件添加注释时需要使用的评估 ID。

以下示例是 JSON 响应示例:

{
  "tokenProperties": {
    "valid": true,
    "androidPackageName": "com.example.app" or "iosBundleId": "com.example.app",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "expectedAction": "USER_ACTION"
  },
  "name": "projects/PROJECT_ID/assessments/b6ac310000000000X",
  "accountDefenderAssessment": {
    labels: ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

accountDefenderAssessment 字段可以具有以下任意值:

说明
SUSPICIOUS_LOGIN_ACTIVITY 表示请求涉及高风险 包括撞库攻击或账号盗用
SUSPICIOUS_ACCOUNT_CREATION 表示相应请求存在高滥用账号创建风险。
PROFILE_MATCH

表示用户的属性与之前为此特定用户看到的属性匹配。此值 表示此用户使用的可信设备之前曾用于 访问您的移动应用。

只有在以下情况下,系统才会返回 PROFILE_MATCH

  • 您可以使用多重身份验证 (MFA) 或双重身份验证 (2FA),reCAPTCHA 账号卫士会在用户通过 MFA 或 2FA 挑战后将用户个人资料标记为可信。
  • 您需要为评估添加 LEGITIMATEPASSED_TWO_FACTOR 注解,并且 reCAPTCHA 账号卫士标记了相应的用户 受信任的个人资料。

为事件添加注解,以调整网站专用模型

如需向 reCAPTCHA 账号卫士提供更多信息并改进网站专属检测模型,您必须通过创建评估来为已评估的事件添加注释。

如需为评估添加注释,请向 projects.assessments.annotate 方法发送包含评估 ID 的请求。在该请求的正文中, 提供有关评估中描述事件的更多信息。

如需为评估添加注解,请执行以下操作:

  1. 根据您的使用场景确定要在请求 JSON 正文中添加的信息和标签。

    下表列出了可用于为事件添加注解的标签和值:

    标签 说明 请求示例
    reasons 必需。用于支持您的评估的标签。

    在 事件发生后几秒或几分钟内显示的“reasons”标签 因为它们会影响实时检测。

    如需查看可能值的列表,请参阅原因值

    示例:如需检测账号盗用,请使用 CORRECT_PASSWORDINCORRECT_PASSWORD 值注解输入的密码是否正确。如果您部署了自己的 MFA, 您可以添加以下值:INITIATED_TWO_FACTORPASSED_TWO_FACTORFAILED_TWO_FACTOR

          {
          "reasons": ["INCORRECT_PASSWORD"]
          }
        
    annotation 可选。用于表示 评估的合法性。

    提供有关登录和 注册事件,以便在 annotation 标签。

    可能的值:LEGITIMATEFRAUDULENT

    您可以随时发送此类信息,也可以在批处理作业中发送。 不过,我们建议您在几秒钟或几分钟内发送此信息 因为它们会影响实时检测。

          {
           "annotation": "LEGITIMATE"
          }
    
      
    accountId

    可选。用于将账号 ID 与事件相关联的标签。

    如果您创建的评估没有账号 ID,请使用此标签提供账号 事件的 ID(只要可用)。

      {
       "accountId": "ACCOUNT_ID"
      }
  2. 使用适当的标签创建注解请求。

    在使用任何请求数据之前,请先进行以下替换:

    • ASSESSMENT_ID:从 projects.assessments.create 调用返回的 name 字段的值。
    • ANNOTATION:可选。指示评估结果是合法还是欺诈的标签。
    • REASONS:可选。支持您的注解的原因。如需查看可能值的列表,请参阅原因值
    • ACCOUNT_ID:可选。与您应用中的用户账号唯一关联的标识符。

    如需了解详情,请参阅注解标签

    HTTP 方法和网址:

    POST https://recaptchaenterprise.googleapis.com/v1/ASSESSMENT_ID:annotate

    请求 JSON 正文:

    {
      "annotation": ANNOTATION,
      "reasons": REASONS,
      "accountId": ACCOUNT_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/ASSESSMENT_ID:annotate"

    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/ASSESSMENT_ID:annotate" | Select-Object -Expand Content

    您应该会收到一个成功的状态代码 (2xx) 和一个空响应。

代码示例

Java

如需向 reCAPTCHA 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Annotation;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Reason;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentResponse;
import com.google.recaptchaenterprise.v1.AssessmentName;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class AnnotateAccountDefenderAssessment {

  public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
    // TODO(developer): Replace these variables before running the sample.
    // projectID: GCloud Project id.
    String projectID = "project-id";

    // assessmentId: Value of the 'name' field returned from the CreateAssessment call.
    String assessmentId = "account-defender-assessment-id";

    // accountId: Set the accountId corresponding to the assessment id.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    annotateAssessment(projectID, assessmentId, accountId);
  }

  /**
   * Pre-requisite: Create an assessment before annotating. Annotate an assessment to provide
   * feedback on the correctness of recaptcha prediction.
   */
  public static void annotateAssessment(
      String projectID, String assessmentId, String accountId) throws IOException {

    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {
      // Build the annotation request.
      // For more info on when/how to annotate, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/annotate-assessment#when_to_annotate
      AnnotateAssessmentRequest annotateAssessmentRequest =
          AnnotateAssessmentRequest.newBuilder()
              .setName(AssessmentName.of(projectID, assessmentId).toString())
              .setAnnotation(Annotation.LEGITIMATE)
              .addReasons(Reason.PASSED_TWO_FACTOR)
              .setAccountId(accountId)
              .build();

      // Empty response is sent back.
      AnnotateAssessmentResponse response = client.annotateAssessment(annotateAssessmentRequest);
      System.out.println("Annotated response sent successfully ! " + response);
    }
  }
}

启用 reCAPTCHA 账号卫士

针对 reCAPTCHA 账号卫士配置您的移动应用后, 您可以启用 reCAPTCHA 账号卫士。

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

    前往 reCAPTCHA

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

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

  3. 点击 设置
  4. 账号卫士窗格中,点击配置

  5. 配置账号卫士对话框中,点击启用,然后点击保存

启用 reCAPTCHA 账号卫士的操作可能需要几个小时才能传播到我们的系统。启用该功能的操作传播到我们的系统后,您将在评估过程中开始接收与账号卫士相关的响应。

后续步骤