如何让RTK Query传递的认证在Firebase实时数据库安全规则中生效?
前端已通过Firebase登录API完成认证,通过认证变更监听器获取令牌并传递至后端,相关代码配置如下:
RTK Query通用配置
reducerPath: "api", baseQuery: fetchBaseQuery({ baseUrl: "https://us-central1.cloudfunctions.net/api", mode: "cors", prepareHeaders: (headers) => { headers.set("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE"); headers.set("Access-Control-Allow-Origin", "*"); headers.set("Access-Control-Allow-Headers", "Content-Type"); const authToken = localStorage.getItem("AuthToken"); if (authToken) headers.set("authorization", authToken); return headers; }, }), endpoints: (builder) => ({ getWorkouts: builder.query<GetWorkoutList, string>({ query: (userId) => ({ url: `/workouts/${userId}`, }), }), // ---rest of endpoints---
前端认证状态监听代码
useEffect(() => { const unsubscribe = onAuthStateChanged(auth, async (userInfo) => { setUser(userInfo); if (userInfo === null) { localStorage.clear(); } else { const token = await userInfo.getIdToken(true); localStorage.setItem("AuthToken", `Bearer ${token}`); } }); return unsubscribe; }, [user]);
云函数令牌验证代码
const decodedIdToken = await adminApp.auth().verifyIdToken(idToken);
实时数据库安全规则
"users":{ "$userId":{ ".write": "$userId == auth.uid", ".read": "$userId == auth.uid", }, }
当前问题:使用Admin权限访问实时数据库时会绕过安全规则,导致数据库中的auth对象为null,无法通过规则校验。需要明确缺失的关键步骤,让请求实时数据库时携带认证对象,使安全规则生效。
核心问题是:默认情况下Firebase Admin SDK访问实时数据库时会以特权身份操作,直接跳过安全规则,不会自动携带用户的认证信息。要让安全规则生效,必须在云函数中模拟用户身份访问数据库,具体操作如下:
保留令牌验证步骤
你已经通过verifyIdToken拿到了解码后的decodedIdToken,其中包含用户的uid,这一步无需改动,继续保留即可。创建绑定用户身份的数据库引用
不要直接使用adminApp.database().ref()这种特权引用,而是通过withAuth()方法生成绑定用户UID的数据库引用。基于该引用的所有操作都会触发安全规则,且规则中的auth.uid会被设置为指定的用户ID。示例代码:
// 验证令牌并提取用户UID const decodedIdToken = await adminApp.auth().verifyIdToken(idToken); const userId = decodedIdToken.uid; // 创建带用户身份的数据库引用 const userDbRef = adminApp.database().ref().withAuth({ uid: userId }); // 使用该引用执行数据库操作,比如读取用户数据 const userData = await userDbRef.child(`users/${userId}`).get();清理前端不必要的CORS头设置
你在RTK Query的prepareHeaders中设置的Access-Control-Allow-Origin等CORS头属于后端响应头,不应该由前端请求设置。前端只需要确保请求开启跨域模式即可,这些头应该在云函数的响应中配置,否则可能引发请求异常。
完成以上修改后,数据库操作会严格遵守安全规则,auth对象不再为null,auth.uid会匹配当前用户的UID,从而通过规则校验。
内容的提问来源于stack exchange,提问作者Kasey Kaufmann

