使用 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 对报告很重要:

  • 关闭的高信任度标准:影响路线的事件(例如道路封闭)可能会显著改变所有驾驶员的路线规划行为。为了保护地图免受潜在的破坏、网络垃圾或不准确的报告的影响,谷歌用于封路中断的审核基础设施依赖于强大的设备和应用完整性信号。
  • 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 Console 中“会员”标签页中的团队 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. 一旦您确定大部分流量都经过验证,并且合法用户已将您的应用程序更新到包含您的应用程序检查实现的版本,即可启用强制执行。
  3. 启用强制执行后,App Check 会拒绝所有没有有效 App Check 令牌的流量。