SafetyNet 安全浏览 API

SafetyNet 安全浏览 API 是由 Google Play 服务 提供支持的库,可提供服务来确定 Google 是否已将 URL 标记为已知威胁。

您的应用可以使用此 API 来确定 Google 是否已将特定 URL 分类为已知威胁。在内部,SafetyNet 实现了一个 Google 开发的安全浏览网络协议 v4 的客户端。客户端代码和 v4 网络协议均旨在保护用户的隐私,并将电池和带宽消耗降至最低。使用此 API 以最优化资源的方式充分利用 Google 的安全浏览服务,而无需实现其网络协议。

本文档介绍如何使用 SafetyNet 安全浏览查找 API 检查 URL 是否存在已知威胁。

服务条款

通过使用安全浏览 API,您同意受 服务条款 的约束。在访问安全浏览 API 之前,请阅读并了解所有适用的条款和政策。

请求和注册 Android API 密钥

在使用安全浏览 API 之前,请创建并注册 Android API 密钥。有关具体步骤,请参阅有关 安全浏览入门 的页面。

添加 SafetyNet API 依赖项

在使用安全浏览 API 之前,请将 SafetyNet API 添加到您的项目中。如果您使用的是 Android Studio,请将此依赖项添加到您的应用级 Gradle 文件中。有关更多信息,请参阅 使用 SafetyNet 防范安全威胁

初始化 API

要使用安全浏览 API,您必须通过调用 initSafeBrowsing() 并等待其完成来初始化 API。以下代码片段提供了一个示例

Kotlin

Tasks.await(SafetyNet.getClient(this).initSafeBrowsing())

Java

Tasks.await(SafetyNet.getClient(this).initSafeBrowsing());

请求 URL 检查

您的应用可以使用 URL 检查来确定 URL 是否构成已知威胁。某些威胁类型可能与您的特定应用无关。API 允许您选择哪些威胁类型对您的需求很重要。您可以指定多种已知威胁类型。

发送 URL 检查请求

API 与使用的方案无关,因此您可以使用或不使用方案传递 URL。例如,两者

Kotlin

var url = "https://www.google.com"

Java

String url = "https://www.google.com";

Kotlin

var url = "www.google.com"

Java

String url = "www.google.com";

都是有效的。

以下代码演示了如何发送 URL 检查请求

Kotlin

SafetyNet.getClient(this).lookupUri(
       url,
       SAFE_BROWSING_API_KEY,
       SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,
       SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING
)
       .addOnSuccessListener(this) { sbResponse ->
           // Indicates communication with the service was successful.
           // Identify any detected threats.
           if (sbResponse.detectedThreats.isEmpty()) {
               // No threats found.
           } else {
               // Threats found!
           }
       }
       .addOnFailureListener(this) { e: Exception ->
           if (e is ApiException) {
               // An error with the Google Play Services API contains some
               // additional details.
               Log.d(TAG, "Error: ${CommonStatusCodes.getStatusCodeString(e.statusCode)}")

               // Note: If the status code, s.statusCode,
               // is SafetyNetStatusCode.SAFE_BROWSING_API_NOT_INITIALIZED,
               // you need to call initSafeBrowsing(). It means either you
               // haven't called initSafeBrowsing() before or that it needs
               // to be called again due to an internal error.
           } else {
               // A different, unknown type of error occurred.
               Log.d(TAG, "Error: ${e.message}")
           }
       }

Java

SafetyNet.getClient(this).lookupUri(url,
         SAFE_BROWSING_API_KEY,
         SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,
         SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING)
   .addOnSuccessListener(this,
       new OnSuccessListener<SafetyNetApi.SafeBrowsingResponse>() {
           @Override
           public void onSuccess(SafetyNetApi.SafeBrowsingResponse sbResponse) {
               // Indicates communication with the service was successful.
               // Identify any detected threats.
               if (sbResponse.getDetectedThreats().isEmpty()) {
                   // No threats found.
               } else {
                   // Threats found!
               }
        }
   })
   .addOnFailureListener(this, new OnFailureListener() {
           @Override
           public void onFailure(@NonNull Exception e) {
               // An error occurred while communicating with the service.
               if (e instanceof ApiException) {
                   // An error with the Google Play Services API contains some
                   // additional details.
                   ApiException apiException = (ApiException) e;
                   Log.d(TAG, "Error: " + CommonStatusCodes
                       .getStatusCodeString(apiException.getStatusCode()));

                   // Note: If the status code, apiException.getStatusCode(),
                   // is SafetyNetStatusCode.SAFE_BROWSING_API_NOT_INITIALIZED,
                   // you need to call initSafeBrowsing(). It means either you
                   // haven't called initSafeBrowsing() before or that it needs
                   // to be called again due to an internal error.
               } else {
                   // A different, unknown type of error occurred.
                   Log.d(TAG, "Error: " + e.getMessage());
               }
           }
   });

读取 URL 检查响应

使用返回的 SafetyNetApi.SafeBrowsingResponse 对象,调用其 getDetectedThreats() 方法,该方法返回一个 SafeBrowsingThreat 对象列表。如果返回的列表为空,则 API 未检测到任何已知威胁。如果列表不为空,请在列表中的每个元素上调用 getThreatType() 以确定 API 检测到的已知威胁。

要查看建议的警告语言,请参阅安全浏览 API 开发人员指南

指定感兴趣的威胁类型

SafeBrowsingThreat 类中的常量包含当前支持的威胁类型。

威胁类型 定义
TYPE_POTENTIALLY_HARMFUL_APPLICATION 此威胁类型标识被标记为包含潜在有害应用程序的页面的 URL。
TYPE_SOCIAL_ENGINEERING 此威胁类型标识被标记为包含社交工程威胁的页面的 URL。

使用 API 时,您将威胁类型常量作为参数添加。您可以根据应用需要添加任意数量的威胁类型常量,但只能使用未标记为已弃用的常量。

关闭安全浏览会话

如果您的应用在较长时间内不需要使用安全浏览 API,请检查应用中所有必要的 URL,然后使用shutdownSafeBrowsing() 方法关闭安全浏览会话。

Kotlin

SafetyNet.getClient(this).shutdownSafeBrowsing()

Java

SafetyNet.getClient(this).shutdownSafeBrowsing();

建议您在 Activity 的onPause() 方法中调用shutdownSafeBrowsing(),并在 Activity 的onResume() 方法中调用initSafeBrowsing()。但是,请确保initSafeBrowsing() 已执行完毕,然后再调用lookupUri()。通过确保会话始终保持最新,您可以减少应用内部错误的可能性。

SafetyNet 安全浏览 API 收集的数据

SafetyNet 安全浏览 API 在与 Android 上的安全浏览服务通信时会自动收集以下数据。

数据 描述
应用活动 在本地哈希前缀匹配后收集 URL 的哈希前缀,以用于检测恶意 URL。

虽然我们的目标是尽可能透明,但您全权负责决定如何响应Google Play 的数据安全部分表单,其中涉及您应用的用户数据收集、共享和安全实践。