使用AWS Amplify Cognito的Flutter应用,如何通过Cloud Functions绕过Firestore安全规则?
基于AWS Amplify Cognito+Cloud Functions安全访问Firestore的实现方案
1. 核心逻辑
Cloud Functions通过Firebase Admin SDK操作Firestore时会自动绕过安全规则,但必须在函数内部自行验证Cognito用户的合法性,确保只有授权用户能执行操作。
2. 步骤实现
2.1 在Cloud Functions中验证Cognito令牌
首先安装AWS SDK依赖,在函数目录执行:
npm install aws-sdk
编写令牌验证函数,调用Cognito官方接口校验令牌有效性:
const AWS = require('aws-sdk'); const cognito = new AWS.CognitoIdentityServiceProvider({ region: '你的AWS区域' }); async function verifyCognitoToken(token) { try { // 从令牌中解析用户池ID和客户端ID(也可直接硬编码,避免解析风险) const decoded = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); const userPoolId = decoded.iss.split('/').pop(); const clientId = decoded.client_id; // 调用Cognito校验接口 const params = { AccessToken: token, // 若传ID Token则改用IdToken参数 UserPoolId: userPoolId, ClientId: clientId }; await cognito.getUser(params).promise(); return decoded; // 返回解码后的用户信息,包含用户ID等核心字段 } catch (err) { throw new Error('无效的Cognito令牌'); } }
2.2 编写Firestore操作的Cloud Function
验证令牌通过后,用Admin SDK执行Firestore操作:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.getProtectedUserData = functions.https.onCall(async (data, context) => { const cognitoToken = data.token; if (!cognitoToken) { throw new functions.https.HttpsError('invalid-argument', '缺少Cognito令牌'); } try { const user = await verifyCognitoToken(cognitoToken); // 根据Cognito用户ID查询对应的Firestore数据 const userDoc = await admin.firestore().collection('users').doc(user.sub).get(); if (!userDoc.exists) { throw new functions.https.HttpsError('not-found', '用户数据不存在'); } return userDoc.data(); } catch (err) { throw new functions.https.HttpsError('unauthenticated', err.message); } });
2.3 Flutter客户端调用Cloud Function
通过Amplify获取用户令牌,再调用Firebase Cloud Function:
import 'package:firebase_functions/firebase_functions.dart'; import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; import 'package:amplify_flutter/amplify_flutter.dart'; Future<Map<String, dynamic>> fetchProtectedUserData() async { // 获取当前登录用户的Cognito Access Token final authSession = await Amplify.Auth.fetchAuthSession(); final accessToken = (authSession as CognitoAuthSession).userPoolTokens?.accessToken; if (accessToken == null) { throw Exception('用户未登录'); } // 调用Cloud Function final functions = FirebaseFunctions.instance; final response = await functions.httpsCallable('getProtectedUserData').call({ 'token': accessToken }); return response.data; }
2.4 安全加固
- 给Cloud Functions配置IAM权限,允许调用
cognito-idp:GetUser接口,避免权限不足 - 修改Firestore安全规则,禁止客户端直接访问,强制所有操作走Cloud Functions:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if false; } } }
内容的提问来源于stack exchange,提问作者MaryKor
相关产品推荐
相关产品推荐

