Flutter调用Firebase HTTPS云函数时无法获取调用者UID的问题
问题根源
你当前使用的onRequest类型HTTPS云函数不会自动解析请求携带的Firebase Auth身份凭证,且如果直接将云函数HTTP地址生成二维码、扫码后通过系统浏览器打开请求,Flutter端的用户登录态根本不会被带入请求,自然无法获取触发用户的UID。
解决方案
你可以根据业务场景二选一:
方案1:改用onCall可调用云函数(推荐)
可调用云函数由Firebase SDK自动处理身份校验逻辑,不需要手动解析令牌,实现更简洁。
- 云函数端代码修改如下:
exports.create = functions.https.onCall(async (data, context) => { // 校验用户登录状态 if (!context.auth) { throw new functions.https.HttpsError('unauthenticated', '用户未登录,无权操作'); } // 直接从上下文获取触发用户UID const uid = context.auth.uid; // 写入数据库时可以关联UID const docRef = await admin.firestore().collection('games').add({ points: 0, createdBy: uid, createTime: admin.firestore.FieldValue.serverTimestamp() }); return {docId: docRef.id}; });
- Flutter端适配:
二维码内容不要存纯HTTP触发地址,改为存可调用函数的标识。用户扫码后不要跳转外部浏览器,直接在Flutter应用内通过官方云函数SDK调用:
// 引入cloud_functions依赖后调用 final callable = FirebaseFunctions.instance.httpsCallable('create'); final res = await callable();
调用时SDK会自动携带当前已登录用户的认证信息,云函数端可以直接读取到UID。
方案2:保留onRequest类型,手动校验身份令牌
如果你需要保留HTTP触发的形式,需要手动在请求中携带、校验用户ID令牌:
- 云函数端代码修改如下:
exports.create = functions.https.onRequest(async (request, response) => { // 从请求头提取身份令牌 const authHeader = request.headers.authorization; const idToken = authHeader?.startsWith('Bearer ') ? authHeader.split('Bearer ')[1] : null; if (!idToken) { return response.status(401).send('缺少身份凭证'); } try { // 校验令牌合法性,解析用户信息 const decodedToken = await admin.auth().verifyIdToken(idToken); const uid = decodedToken.uid; await admin.firestore().collection('games').add({ points: 0, createdBy: uid }); return response.status(200).send('创建成功'); } catch (err) { return response.status(401).send('身份凭证无效'); } });
- Flutter端适配:
用户扫码拿到云函数地址后,先获取当前登录用户的ID令牌,将令牌放入请求头后在应用内发起HTTP请求,不要跳转外部浏览器打开地址:
import 'package:firebase_auth/firebase_auth.dart'; import 'package:http/http.dart' as http; // 扫码后执行逻辑 final currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) { // 处理未登录场景,比如跳登录页 return; } final idToken = await currentUser.getIdToken(); final resp = await http.post( Uri.parse('扫码得到的云函数地址'), headers: { 'Authorization': 'Bearer $idToken' } );
核心注意点:无论用哪种方案,都不能让用户扫码后跳转到系统浏览器触发云函数,系统浏览器无法读取Flutter应用内的Firebase登录态,必然拿不到用户UID,所有请求逻辑必须在Flutter应用内部完成。
内容的提问来源于stack exchange,提问作者Usama Naufer
相关产品推荐
相关产品推荐

