我正在开发一个使用 Vertex AI for Firebase SDK 的 Flutter 应用程序。当我仅使用文本提示而不包含任何 Firebase 存储 URL 时,一切正常。然而,当我包含 Firebase 存储 URL 时,我会收到以下错误消息:调用者没有权限。
我发现将 Firebase 存储的安全规则更改为以下内容可以解决问题,但这些规则并不安全:
rules_version = '2';service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if true; } }}
Stream<String?> generateTextFromMediaStream(String promptText, List<String>? mediaPaths) async* { final prompt = TextPart(promptText); List mediaPartsFuture = []; if (mediaPaths != null) { mediaPartsFuture = mediaPaths.map((path) { final mimeType = getMimeType(path); return FileData(mimeType, path); }).toList(); } final response = _model.generateContentStream([ Content.multi([prompt, ...mediaPartsFuture]) ]); await for (final chunk in response) { yield chunk.text; } }
错误消息:
I/flutter (12483): 调用者没有权限I/flutter (12483): #0 parseGenerateContentResponse (package:google_generative_ai/src/api.dart:558:54)I/flutter (12483): #1 _MapStream._handleData (dart:async/stream_pipe.dart:213:31)I/flutter (12483): #2 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)I/flutter (12483): #3 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)I/flutter (12483): #4 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)I/flutter (12483): #5 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)I/flutter (12483): #6 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)I/flutter (12483): #7 _StreamController._add (dart:async/stream_controller.dart:658:7)I/flutter (12483): #8 _StreamController.add (dart:async/stream_controller.dart:606:5)I/flutter (12483): #9 _AsyncStarStreamController.add (dart:async-patch/async_patch.dart:76:16)I/flutter (12483): #10 HttpApiClient.streamRequest (package:google_generative_ai/src/client.dart)I/flutter (12483): <asynchronous suspension>I/flutter (12483): #11 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:152:3)I/flutter (12483): <asynchronous suspension>
我在 Google Cloud API 中看到了以下错误:
Firebase ML API:
- 方法:google.firebase.machinelearning.v2beta.PredictionService.StreamGenerateContent(100% 错误)
附加上下文:
Flutter 3.22.0 firebase_vertexai 0.1.0+1
有人能指导我可能导致此权限错误的原因以及如何在不损害 Firebase 存储规则安全性的情况下解决它吗?
我尝试过的方法:
- 我尝试使用以下更严格的安全规则,但它们不起作用:
rules_version = '2';service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if request.auth != null || request.auth.token.email.matches('.*gserviceaccount.*') || request.auth.token.email == '[email protected]'|| request.auth.token.email == 'service-PROJECT_NUMBER@gcp-sa-aiplatform-cc.iam.gserviceaccount.com'|| request.auth.token.email == '[email protected]'|| request.auth.token.email == '[email protected]'|| request.auth.token.email == '[email protected]' || request.auth.token.email == '[email protected]' || request.auth.token.email == 'service-PROJECT_NUMBER@gcp-sa-firebasestorage.iam.gserviceaccount.com'; } }}
我用我的项目编号替换了 PROJECT_NUMBER
- 我为以下角色(Cloud Storage for Firebase Admin)分配了服务账户的角色:
- [email protected]
- [email protected]
- [email protected]
- [email protected]
回答:
可能 Firebase
VertexAI
SDK 使用服务账户访问存储桶(或者根本不使用身份验证)。
编辑:主要解决方案是使用当前的 FirebaseAuth
实例对 VertexAI
服务或 SDK 进行身份验证,以便能够对 Firebase Cloud Storage 进行经过身份验证的请求。
要对 VertexAI
SDK 进行身份验证,请在初始化新的 VertexAI
实例时将当前的 FirebaseAuth
实例传递给它,如下所示:
final vertexAI = FirebaseVertexAI.instanceFor( auth: FirebaseAuth.instance, // 如果用户已通过身份验证,则为现有的 FirebaseAuth 实例 location: 'location');print(vertexAI.auth?.currentUser?.email); // 检查身份验证是否成功。
然而,如果用户未通过身份验证或者资源是最近上传的,以下是一个快速且不完美的解决方案,可能会对你有用:
rules_version = '2';// 授予用户访问与其用户 ID 匹配的节点的权限service firebase.storage { match /b/{bucket}/o { // 文件看起来像:"user/<UID>/path/to/file.txt" match /user/{userId}/{allPaths=**} { // 如果文件在 10 分钟内创建,则允许读取 allow read: if request.time < resource.timeCreated + duration.value(10, 'm'); // 如果已通过身份验证且 UID 匹配或用户具有管理员权限,则允许写入 allow write: if request.auth != null && (request.auth.uid == userId || request.auth.token.admin == true); } }}
否则,你可以自己处理资源下载,然后将其作为原始字节传递给服务。