使用 App Check 保护 Navigation SDK for iOS

Firebase App Check 可屏蔽来自合法应用以外的流量,为您的应用对 Google Maps Platform 的调用提供保护。为此,它会向 App Attest 等证明提供方请求评估应用或设备的真实性。将应用与 App Check 集成后,您可以防范恶意请求和未经授权的请求,从而保护您的结算免受未经授权的费用的侵扰。App Check 还可以显著改进车队应用生态系统中的实时中断报告,从而使使用您应用的所有司机受益。如需了解详情,请参阅 中断报告

为何使用 App Check?

App Check 可保护 Navigation SDK for iOS 的两个不同方面:主要导航功能和中断报告。

App Check 有助于屏蔽来自恶意来源或未经授权的来源的主要 Navigation SDK for iOS 请求。这可以直接保护您的项目免受结算欺诈和配额耗尽的影响,从而使您受益。

中断报告

如果您的应用支持实时中断报告和投票功能,强烈建议您使用 App Check。启用 App Check 可确保您的司机获得最准确的路线,并考虑到所有实时反馈。

App Check 对报告的重要性:

  • 高信任度关闭: 影响路线的事件(例如道路封闭)可能会显著改变所有司机的路线规划行为。为了保护地图免受潜在的恶意破坏、网络垃圾或不准确报告的影响,Google 的封路中断审核基础架构依赖于强大的设备和应用完整性信号。
  • App Check 如何验证报告: 从 Navigation SDK for iOS 发送的用户报告和投票包含 App Check 令牌,Google 的后端会使用该令牌来验证反馈的合法性,从而提高其信任度,并允许对其进行评估以了解其对已发布的地图的影响。
  • 忽略 App Check 的影响: 如果提交的报告没有有效的 App Check 令牌,系统会根据信任度较低的模型对其进行评估,并且可能仅将其作为静默信号进行处理。这意味着,虽然您的用户仍然可以报告和投票,但他们的报告不太可能在地图上显示或影响其他司机的路线,并且需要进行额外的验证。

App Check 适合我吗?

在大多数情况下,建议使用 App Check;但是,在以下情况下,不需要或不支持 App Check:

  • 私有应用或实验性应用: 如果您的应用无法公开访问,则不需要 App Check。
  • 已破解的设备: 推荐的证明提供方可防止 Navigation SDK for iOS 在不可信的设备(例如已启用 root 权限或已越狱的手机)上运行。如需支持这些设备,请部署自定义证明提供方

实现步骤概览

概括来讲,您需要按照以下步骤将应用与 App Check 集成:

  1. 将 Firebase 添加到您的应用。
  2. 添加 App Check 库并初始化 App Check。
  3. 添加令牌提供方。此步骤会调用您选择的证明提供方来验证设备或应用的完整性。
  4. 初始化 Navigation 和 App Check API。
  5. 启用调试功能。这在开发期间或持续集成 (CI) 环境中非常有用。
  6. 在启用强制执行之前,请监控应用请求。这样,您就可以无缝强制执行 App Check,而不会中断用户体验。

规划 App Check 集成时的注意事项

  • 证明提供方配额: 我们推荐的证明提供方(DeviceCheck 或 App Attest)受 Apple 设置的配额和限制的约束。
  • 启动延迟时间: 在大多数情况下,用户在正常使用期间不会遇到延迟,因为 App Check 令牌会缓存在设备上。系统会在后台自动刷新 App Check 令牌,以确保在令牌过期之前保持无缝性能。但是,如果没有有效的 App Check 令牌,应用用户在启动时会遇到一些延迟。例如,当缓存的令牌过期或丢失时,冷启动期间会发生此延迟。
  • 令牌 TTL: 存留时间 (TTL) 决定了 App Check 令牌在需要刷新之前有效的时长。您可以在 Firebase 控制台中将此时长配置为 30 分钟到 7 天之间。建议将 1 小时作为安全基准时长,但 SDK 会自动尝试在 TTL 时长的一半左右进行后台刷新。如需了解有关控制台操作的逐步说明,请参阅 Firebase App Check 文档

将应用与 App Check 集成

前提条件和要求

  • 安装了 Navigation SDK for iOS 11.0 或更高版本的应用。
  • 应用的软件包 ID
  • Apple Developer 控制台的“会员资格”标签页中的团队 ID。
  • 如果您计划使用 DeviceCheck,则需要您的 私钥文件密钥 ID
  • 您必须是 Google Cloud 控制台中应用的所有者。
  • Google Cloud 控制台中应用的项目 ID。

第 1 步:将 Firebase 添加到您的应用

按照 Firebase 开发者文档中的说明 将 Firebase 添加到您的应用。将 GoogleService-Info.plist 文件(未经修改)添加到项目的根级别。

AppDelegate 文件中,导入以下模块:

Swift

import FirebaseCore
import FirebaseAppCheck
import GoogleNavigation

Objective-C

@import FirebaseCore;
@import FirebaseAppCheck;
@import GoogleNavigation;

第 2 步:添加 App Check 库并初始化 App Check

Firebase 为每个默认证明提供方提供了说明。这些说明介绍了如何设置 Firebase 项目并将 App Check 库添加到您的应用。按照提供的代码示例初始化 App Check。

  1. 按照 Firebase 说明添加 App Check 库:
  2. AppDelegate 中初始化 App Check:
    • 如果您使用的是 App Attest,请创建 AppCheckProviderFactory 的实现,并在调用 FirebaseApp.configure() 之前注册该实现:

      Swift

      class YourAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
          func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
              return AppAttestProvider(app: app)
          }
      }
      // In application(_:didFinishLaunchingWithOptions:)
      let providerFactory = YourAppCheckProviderFactory()
      AppCheck.setAppCheckProviderFactory(providerFactory)
      FirebaseApp.configure()

      Objective-C

      #import <FirebaseCore/FirebaseCore.h>
      #import <FirebaseAppCheck/FirebaseAppCheck.h>
      
      @interface YourAppCheckProviderFactory : NSObject <FIRAppCheckProviderFactory>
      @end
      
      @implementation YourAppCheckProviderFactory
      - (nullable id<FIRAppCheckProvider>)createProviderWithApp:(FIRApp *)app {
          return [[FIRAppAttestProvider alloc] initWithApp:app];
      }
      @end
      
      // In application:didFinishLaunchingWithOptions:
      YourAppCheckProviderFactory *providerFactory = [[YourAppCheckProviderFactory alloc] init];
      [FIRAppCheck setAppCheckProviderFactory:providerFactory];
      [FIRApp configure];
    • 如果您使用的是 DeviceCheck,请使用以下代码设置工厂:

      Swift

      AppCheck.setAppCheckProviderFactory(DeviceCheckProviderFactory())

      Objective-C

      FIRDeviceCheckProviderFactory *providerFactory = [[FIRDeviceCheckProviderFactory alloc] init];
      [FIRAppCheck setAppCheckProviderFactory:providerFactory];

第 3 步:添加令牌提供方

在应用的根级别创建一个名为 AppCheckTokenProvider 的文件(如果您使用 Objective-C,则创建两个名为 AppCheckTokenProvider.hAppCheckTokenProvider.m 的文件)。

此类必须符合 GMSAppCheckTokenProvider 协议并实现方法 fetchAppCheckTokenWithCompletion

Swift

import Foundation
import FirebaseAppCheck
import GoogleNavigation

class AppCheckTokenProvider: NSObject, GMSAppCheckTokenProvider {
    func fetchAppCheckToken(completion: @escaping (String?, Error?) -> Void) {
        AppCheck.appCheck().token(forcingRefresh: false) { token, error in
            if let error = error {
                print("App Check Error: \(error)")
                completion(nil, error)
                return
            }
            guard let token = token else {
                completion(nil, NSError(domain: "AppCheck", code: -1, userInfo: [NSLocalizedDescriptionKey: "Token is nil"]))
                return
            }
            print("App Check Token: \(token.token)")
            completion(token.token, nil)
        }
    }
}

Objective-C

// AppCheckTokenProvider.h
#import <Foundation/Foundation.h>
#import <GoogleNavigation/GoogleNavigation.h>

NS_ASSUME_NONNULL_BEGIN

@interface AppCheckTokenProvider : NSObject <GMSAppCheckTokenProvider>
@end

NS_ASSUME_NONNULL_END
// AppCheckTokenProvider.m
#import "AppCheckTokenProvider.h"
#import <FirebaseAppCheck/FirebaseAppCheck.h>

@implementation AppCheckTokenProvider
- (void)fetchAppCheckTokenWithCompletion:(void (^)(NSString * _Nullable token, NSError * _Nullable error))completion {
    [[FIRAppCheck appCheck] tokenForcingRefresh:NO
                                     completion:^(FIRAppCheckToken * _Nullable token, NSError * _Nullable error) {
        if (token) {
            completion(token.token, nil);
        } else {
            completion(nil, error);
        }
    }];
}
@end

第 4 步:初始化 Navigation 和 App Check API

初始化 Navigation SDK for iOS(使用 GMSServices),并通过将共享的不透明服务句柄转换为 GMSServices 来注册令牌提供方实例:

Swift

// In application(_:didFinishLaunchingWithOptions:)
GMSServices.provideAPIKey("YOUR_API_KEY")

// Register your App Check token provider before initializing Navigation SDK for iOS
if let services = GMSServices.sharedServices() as? GMSServices {
    services.appCheckTokenProvider = AppCheckTokenProvider()
}

Objective-C

// In application:didFinishLaunchingWithOptions:
[GMSServices provideAPIKey:@"YOUR_API_KEY"];

// Register your App Check token provider before initializing Navigation SDK for iOS
((GMSServices *)[GMSServices sharedServices]).appCheckTokenProvider = [[AppCheckTokenProvider alloc] init];

第 5 步:启用调试功能(可选)

为 Navigation SDK for iOS 强制执行 App Check 后,依赖于 Navigation SDK for iOS 的应用功能将无法在模拟器或持续集成 (CI) 环境中运行,因为这些环境不符合有效设备的条件。如需在开发和测试期间在这些环境中运行应用,您需要创建应用的调试 build,该 build 使用 App Check 调试提供方,而不是生产证明提供方。

  1. AppDelegate 中配置调试提供方工厂:

    Swift

    #if targetEnvironment(simulator)
    let providerFactory = AppCheckDebugProviderFactory()
    #else
    let providerFactory = YourAppCheckProviderFactory()
    #endif
    AppCheck.setAppCheckProviderFactory(providerFactory)

    Objective-C

    #if TARGET_OS_SIMULATOR
    id<FIRAppCheckProviderFactory> providerFactory = [[FIRAppCheckDebugProviderFactory alloc] init];
    #else
    id<FIRAppCheckProviderFactory> providerFactory = [[YourAppCheckProviderFactory alloc] init];
    #endif
    [FIRAppCheck setAppCheckProviderFactory:providerFactory];
  2. 在 Xcode 项目中启用日志记录,启动应用,然后在控制台日志中找到本地调试令牌。
  3. 复制此调试令牌并将其添加到 Firebase 控制台。如需了解详情,请参阅 Firebase App Check 调试提供方文档

第 6 步:监控应用请求并决定是否强制执行

在启用强制执行之前,请监控应用请求,以确保不会中断合法用户。

  1. 访问 Firebase 控制台中的 App Check 指标屏幕,查看已验证流量与未验证流量的百分比。
  2. 确定大部分流量都已通过验证,并且合法用户已更新到包含 App Check 实现的应用版本后,启用强制执行。
  3. 启用强制执行后,App Check 将拒绝所有没有有效 App Check 令牌的流量。