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

如何在GCP/Firebase中搭建多应用共享的集中式身份认证项目?

跨应用共享Firebase账号方案实现

针对你提出的集中式认证+跨应用共享账号需求,完全可以通过Firebase Functions实现,iOS前端也能完成所有核心操作;同时多Firebase配置文件的区分也有成熟的处理方式,具体方案如下:

一、核心实现逻辑

以Project A作为唯一的认证源和用户数据存储中心,Project B/C不启用本地邮箱/密码认证,可通过两种方式对接Project A:

  1. 调用Project A部署的Firebase Functions完成注册/登录,获取自定义token后登录Project A的Auth系统;
  2. 直接在iOS端初始化Project A的Firebase实例,用其Auth SDK完成原生邮箱/密码认证(更简洁,无需Functions)。

二、Firebase Functions 实现方案(部署在Project A)

如果需要自定义认证逻辑(比如额外参数校验、关联业务数据),可以用Functions封装注册/登录接口:

1. 用户注册接口

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.createUser = functions.https.onCall(async (data) => {
  const { email, password, displayName } = data;
  try {
    // 创建Project A的认证用户
    const user = await admin.auth().createUser({ email, password, displayName });
    // 写入基础用户信息到Firestore
    await admin.firestore().collection("users").doc(user.uid).set({
      email,
      displayName,
      createdAt: admin.firestore.FieldValue.serverTimestamp()
    });
    // 返回自定义token供客户端登录
    const customToken = await admin.auth().createCustomToken(user.uid);
    return { customToken, uid: user.uid };
  } catch (err) {
    throw new functions.https.HttpsError("invalid-argument", err.message);
  }
});

2. 用户登录接口

exports.signInUser = functions.https.onCall(async (data) => {
  const { email } = data;
  try {
    const user = await admin.auth().getUserByEmail(email);
    const customToken = await admin.auth().createCustomToken(user.uid);
    return { customToken, uid: user.uid };
  } catch (err) {
    throw new functions.https.HttpsError("invalid-argument", err.message);
  }
});

三、iOS前端操作实现

方式1:通过Functions对接(适合自定义逻辑场景)

  1. 初始化当前应用的Firebase项目(Project B/C),添加Firebase Functions依赖;
  2. 手动创建Project A的Firebase配置,初始化其Auth实例:
// 初始化Project A的Firebase App
let projectAOptions = FirebaseOptions(
  googleAppID: "PROJECT_A_GOOGLE_APP_ID",
  gcmSenderID: "PROJECT_A_GCM_SENDER_ID"
)
projectAOptions.apiKey = "PROJECT_A_API_KEY"
projectAOptions.projectID = "PROJECT_A_PROJECT_ID"
projectAOptions.bundleID = Bundle.main.bundleIdentifier!
FirebaseApp.configure(name: "ProjectA", options: projectAOptions)

// 获取Project A的Auth实例
guard let projectAAuth = Auth.auth(app: FirebaseApp.app(name: "ProjectA")) else { return }

// 调用Project A的登录函数
let functions = Functions.functions(region: "your-region")
functions.httpsCallable("signInUser").call(["email": "user@example.com"]) { result, error in
  guard let customToken = (result?.data as? [String: Any])?["customToken"] as? String else { return }
  // 用自定义token登录Project A的Auth
  projectAAuth.signIn(withCustomToken: customToken) { authResult, error in
    if let user = authResult?.user {
      // 登录成功,访问Project A的Firestore
      let projectAFirestore = Firestore.firestore(app: FirebaseApp.app(name: "ProjectA"))
      projectAFirestore.collection("users").document(user.uid).getDocument { snapshot, _ in
        print("用户数据:\(snapshot?.data() ?? [:])")
      }
    }
  }
}

方式2:直接多项目初始化(更简洁)

如果不需要自定义逻辑,直接在iOS端同时初始化两个Firebase项目:

  1. 将Project A的GoogleService-Info.plist重命名为GoogleService-Info-ProjectA.plist,添加到项目中;
  2. 初始化双项目并登录:
// 初始化当前应用的主项目(Project B/C)
FirebaseApp.configure()

// 初始化Project A
guard let plistPath = Bundle.main.path(forResource: "GoogleService-Info-ProjectA", ofType: "plist"),
      let options = FirebaseOptions(contentsOfFile: plistPath) else { return }
FirebaseApp.configure(name: "ProjectA", options: options)

// 用Project A的Auth登录
guard let projectAAuth = Auth.auth(app: FirebaseApp.app(name: "ProjectA")) else { return }
projectAAuth.signIn(withEmail: "user@example.com", password: "123456") { authResult, error in
  if let user = authResult?.user {
    // 访问Project A的Firestore
    let firestore = Firestore.firestore(app: FirebaseApp.app(name: "ProjectA"))
    firestore.collection("users").document(user.uid).getDocument { snapshot, _ in
      // 处理用户数据
    }
  }
}

四、iOS中区分多个Firebase配置的方法

  1. 文件重命名:将不同项目的配置文件重命名(如GoogleService-Info-ProjectA.plist),避免文件名冲突;
  2. 指定App名称初始化:初始化时给每个Firebase App分配唯一名称(如ProjectA),后续通过FirebaseApp.app(name: "ProjectA")获取对应项目的Auth、Firestore等实例;
  3. 代码硬编码配置:如果不想添加多个plist文件,直接在代码中创建FirebaseOptions并填入对应项目的API Key、Project ID等参数,灵活度更高。

五、关键注意事项

  • 权限配置:在Project A的Firestore中设置安全规则,确保只有已认证用户能访问自己的数据:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read, write: if request.auth != null && request.auth.uid == uid;
    }
  }
}
  • 控制台配置:在Project A的Firebase控制台添加所有客户端App的Bundle ID,否则无法正常初始化Auth SDK;
  • Token过期处理:自定义token默认有效期1小时,客户端需监听Auth的didChangeAuthState事件,及时刷新token。

内容的提问来源于stack exchange,提问作者Joe Alvini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:15:31