You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xcode项目集成Firebase App Check后Firestore权限问题排查

Firebase App Check集成后Firestore权限问题排查

问题背景

我正尝试在Xcode项目中集成Firebase App Check,确保只有我的应用能访问Firebase Database。已在Firebase控制台完成App Check配置,并用DeviceCheck生成密钥,同时修改了Firestore安全规则,设置为仅当请求携带有效App Check令牌时允许访问(应用无需用户认证)。但应用无法获取数据,控制台提示权限不足;若改为开放规则则能正常访问,说明问题出在App Check的代码集成环节。

当前Firestore规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.token.app_check != null;
    }
  }
}

Swift集成代码

//
//  Gossip_GirlApp.swift
//  Gossip-Girl
//
//  Created by Julius Pleunes on 25/11/2024.
//

import SwiftUI
import Firebase
import FirebaseAppCheck

@main
struct Gossip_GirlApp: App {
    init() {
        FirebaseApp.configure()
        
        // 配置App Check使用DeviceCheck
        AppCheck.setAppCheckProviderFactory(DeviceCheckProviderFactory())
        
        // 调试:开启Firebase日志
        FirebaseConfiguration.shared.setLoggerLevel(.debug)

        print("✅ Firebase 和 App Check 已配置完成")
        
        // 调试:获取App Check令牌
        AppCheck.appCheck().token(forcingRefresh: true) { token, error in
            if let error = error {
                print("⚠️ 获取App Check令牌失败:\(error.localizedDescription)")
            } else if let token = token?.token {
                print("✅ App Check令牌:\(token)")
            } else {
                print("⚠️ App Check令牌为空")
            }
        }

        // 测试Firestore访问
        let db = Firestore.firestore()
        db.collection("posts").getDocuments { snapshot, error in
            if let error = error {
                print("⚠️ 获取帖子失败:\(error.localizedDescription)")
            } else if let documents = snapshot?.documents {
                print("✅ 成功获取帖子:")
                for document in documents {
                    print("\(document.documentID): \(document.data())")
                }
            } else {
                print("⚠️ 'posts'集合中无文档。")
            }
        }
    }

    var body: some Scene {
        WindowGroup {
            MainView() // 以标签栏视图启动
        }
    }
}

控制台错误信息

⚠️ 获取帖子失败:Missing or insufficient permissions.


排查和解决方案

1. 修正Firestore规则:适配未认证场景

你的规则中使用request.auth.token.app_check,但应用无需用户认证,未登录用户的request.auth为空,直接导致规则判定失败。未认证场景下,应使用request.app对象验证App Check令牌:

修改后的规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.app != null;
    }
  }
}

request.app != null表示请求已通过App Check验证,是无需用户登录场景的正确写法。

2. 调整异步调用顺序:确保令牌就绪后再访问Firestore

你在init中同时发起了App Check令牌请求和Firestore请求,但Firestore请求可能在令牌获取完成前就发送了,此时请求未携带有效令牌,触发权限错误。调整代码,让Firestore请求在令牌获取成功后执行:

init() {
    FirebaseApp.configure()
    AppCheck.setAppCheckProviderFactory(DeviceCheckProviderFactory())
    FirebaseConfiguration.shared.setLoggerLevel(.debug)

    print("✅ Firebase 和 App Check 已配置完成")
    
    // 先获取App Check令牌,再发起Firestore请求
    AppCheck.appCheck().token(forcingRefresh: true) { token, error in
        if let error = error {
            print("⚠️ 获取App Check令牌失败:\(error.localizedDescription)")
        } else if let token = token?.token {
            print("✅ App Check令牌:\(token)")
            // 令牌就绪后执行Firestore请求
            self.testFirestoreAccess()
        } else {
            print("⚠️ App Check令牌为空")
        }
    }
}

private func testFirestoreAccess() {
    let db = Firestore.firestore()
    db.collection("posts").getDocuments { snapshot, error in
        if let error = error {
            print("⚠️ 获取帖子失败:\(error.localizedDescription)")
        } else if let documents = snapshot?.documents {
            print("✅ 成功获取帖子:")
            for document in documents {
                print("\(document.documentID): \(document.data())")
            }
        } else {
            print("⚠️ 'posts'集合中无文档。")
        }
    }
}

3. 验证App Check控制台配置

  • 确认Firebase控制台App Check页面已为iOS应用启用DeviceCheck,且正确上传了Apple开发者后台生成的DeviceCheck密钥。
  • 检查GoogleService-Info.plist是否正确添加到项目,其中APP_ID等配置信息无误。
  • 调试阶段可临时启用App Check调试令牌验证规则:
    // 仅调试环境使用
    let providerFactory = AppCheckDebugProviderFactory()
    AppCheck.setAppCheckProviderFactory(providerFactory)
    
    同时在Firebase控制台添加调试令牌,验证通过后再切换回DeviceCheck。

内容的提问来源于stack exchange,提问作者Julius Pleunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:43:31