首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >request.auth.uid不适用于防火墙安全规则。

request.auth.uid不适用于防火墙安全规则。
EN

Stack Overflow用户
提问于 2022-02-21 05:38:07
回答 1查看 455关注 0票数 0

我有如下所示的防火墙DB,uid字段包含添加了文档的经过身份验证的用户的uid

安保作用:

代码语言:javascript
复制
rules_version = '2';
service cloud.firestore {
 match /databases/{database}/documents {
    match /crush/{doc} {
      allow read: if request.auth != null && request.auth.uid == resource.data.uid;
      allow write : if request.auth != null;
      }
    }
}

模拟读取规则工作

然而,在实际的颤振应用程序中,只有DB写工作,读取失败,下面的错误

name__);limitType=LIMIT_TO_FIRST) /Firestore( 6538):(24.0.1)修复:侦听查询(target=Query(target=Query失败):状态{code=PERMISSION_DENIED,description=Missing或权限不足.,cause=null}

这让我相信request.auth.uid是空白的。

该程序如下所示

代码语言:javascript
复制
# landing.dart
# Authentication class is helper for FirebaseAuth.instance 
import 'home.dart';

class Landing extends StatefulWidget {
  const Landing({Key? key}) : super(key: key);

  @override
  State<Landing> createState() => _LandingState();
}

class _LandingState extends State<Landing> {
  dynamic authStream = Authentication().authState;
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: authStream,
        builder: (BuildContext context, AsyncSnapshot<AppUser?> snapshot) {
          if (snapshot.data != null) {
            return Home(snapshot.data);
          }
          else {
            return SignIn(); //via google
          }
        });
  }
}

# home.dart
# Database class is helper for FirebaseFirestore.instance
import 'package:flutter/material.dart';
import 'package:password_safe/models/crush.dart';
import 'package:password_safe/models/user.dart';
import 'package:password_safe/services/authentication.dart';
import 'package:password_safe/services/database.dart';

class Home extends StatefulWidget {
  AppUser? user;

  Home(this.user, {Key? key}) : super(key: key);

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  dynamic streamCrush = Database().getCrushSnapshot;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          provideInput(context, widget.user);
        },
        child: Icon(Icons.add),
      ),
      body: StreamBuilder(
        stream: streamCrush,
        builder: (BuildContext context, AsyncSnapshot<List<Crush>> snapshot) {
          if (snapshot.hasError) {
            return Center(child: Text('Error Ocurred'));
          }
          if (snapshot.connectionState == ConnectionState.waiting) {
            return CircularProgressIndicator();
          }
          return myList(snapshot.data!);
        },
      ),
    );
  }
}

\\ database.dart
import 'dart:developer' as developer;

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:password_safe/models/crush.dart';

class Database {
  late FirebaseFirestore _db;
  late CollectionReference crushCollection;
  final String _logName = "Database";
  static final Database _instance = Database._internal();

  Database._internal() {
    try {
      _db = FirebaseFirestore.instance;
      crushCollection = _db.collection('crush');
    } catch (e) {
      // do something
    }
  }

  factory Database() {
    return _instance;
  }

  Future<void> addCrush(Crush crush) async {
    await crushCollection
        .add(crush.toMap())
        .then(
          (value) => developer.log('adding crush to backend', name: _logName),
        )
        .catchError(
          (error) => developer.log('Error while adding crush',
              name: _logName, error: error),
        );
  }

  Stream<List<Crush>> get getCrushSnapshot {
    return crushCollection
        .snapshots()
        .map((event) => _crushListFromSnapshot(event));
  }

  List<Crush> _crushListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((e) {
      Map<String, dynamic> data = e.data() as Map<String, dynamic>;
      data.addAll({'id': e.id});
      return Crush.fromMap(data);
    }).toList();
  }

  Future<void> deleteCrush(Crush crush) {
    return crushCollection
        .doc(crush.id)
        .delete()
        .then((value) =>
            developer.log('deleting crush from backend', name: _logName))
        .onError((error, stackTrace) => developer.log(
            'error occured while deleting data from crush',
            name: _logName,
            error: error,
            stackTrace: stackTrace));
  }
}

pubspec.yaml

代码语言:javascript
复制
dependencies:
  cloud_firestore:
  google_sign_in: '^4.5.1'
  firebase_auth:
  firebase_core:
  flutter:
    sdk: flutter
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-21 12:36:55

查询约束与安全规则约束不匹配。您正在尝试获取/crush/* (如数据库查询中所示),但您只能按照Firestore安全规则访问/crush/{doc}

即使当前用户实际上是每个文档的作者,查询也会失败。这种行为的原因是,当Cloud应用您的安全规则时,它会根据其潜在的结果集来评估查询,而不是根据数据库中文档的实际属性来评估查询。如果查询可能包含违反安全规则的文档,则查询将失败。

因此,您需要过滤数据库查询,以便将文档的uid字段与auth.uid匹配。就像这样:

代码语言:javascript
复制
var user = FirebaseAuth.instance.currentUser;
db.collection("crush").where(“uid”, "==", user.uid).get()

您可以阅读有关基于auth.id 这里的文档安全和查询的更多信息。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71201642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档