【问题标题】:Flutter Firestore AuthenticationFlutter Firestore 身份验证
【发布时间】:2019-11-22 17:27:37
【问题描述】:

我有一个使用 cloud_firestore 插件进行数据访问的 Flutter 项目。用户对应用程序进行身份验证后,我需要做什么才能将其设置为 Firestore 客户端使用的身份验证?例如,我只启用了这些基本规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;     
    }
    match /users/{userId}/{document=**} {
      allow read, update, delete, create: if request.auth.uid == userId;
    }
    match /ingredients/* {
      allow read, create: if request.auth.uid != null;      
    }
    match /units/* {
      allow read, create: if request.auth.uid != null;      
    }
    match /recipes/* {
      allow read, create, update: if request.auth.uid != null;      
    }
  }
} 

一旦我启用了这些规则,来自我的 Flutter 应用程序的每个请求都开始失败。如果我用他们拥有的小“模拟器”测试 Firestore 规则,它们会按预期工作,因此从 Flutter 应用程序端似乎没有正确设置身份验证。

编辑:添加一些代码示例。

我有使用 Google Auth 的身份验证代码,所以当用户登录时,它看起来像这样:

class Auth implements AuthService {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

GoogleSignIn _googleSignIn = GoogleSignIn(
    scopes: [
      'email',
      'https://www.googleapis.com/auth/contacts.readonly',
    ],
  );


  Future<String> signInWithGoogle() async {
    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth = await googleUser.authentication;

    final AuthCredential credential = GoogleAuthProvider.getCredential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );

    final FirebaseUser user = await _firebaseAuth.signInWithCredential(credential);
    return user.uid;
  }

我已验证用户的身份验证正确。

然后,当访问 Firestore 时,类似:

DocumentSnapshot userSnapshot = await Firestore.instance
          .collection('users')
          .document(userId)
          .collection('shoppingLists')
          .document(listName)
          .get();

我已按照所有指南将 Firebase 和 Firestore 添加到我的应用程序中,但我没有看到任何关于将当前经过身份验证的用户设置为发出 Firestore 请求的用户的具体内容,所以我觉得我是那里缺少一些东西。在进行 Firestore 查询以传入当前用户时,我应该做些什么?

【问题讨论】:

  • 您找到解决此问题的方法了吗?我遇到了同样的问题,我很疯狂,我怎么找不到答案,只是没有任何解决方案的问题。
  • 看看这个答案(“以防万一......”):stackoverflow.com/questions/52812514/…
  • 对我来说一切都很好。当您在 Firestore 中访问引用时,检查“userId”是否具有预期值。 Firestore 规则 UI(左下角)中还有一个非常有用的模拟器,您可以使用它。它会准确地告诉您规则失败的地方。
  • 我有完全相同的问题,使用任何规则也会导致权限被拒绝错误。
  • 现在是 2020 年 4 月,这样一个基本问题仍然没有答案..

标签: flutter google-cloud-firestore firebase-security


【解决方案1】:

答案是不是用户Firestore.instance,因为这会给您一个与Firebase应用断开连接的实例;

改为使用创建您的 Firebase 应用来提供所有密钥,然后针对该应用进行身份验证,然后针对该应用创建一个 Firestore 实例。无法显式传递用户,但代码在内部使用一些逻辑来确定已针对您创建的应用程序进行身份验证的用户。这是我使用的代码:

  Future<void> _authenticate() async {
    FirebaseApp _app = await FirebaseApp.configure(
      name: 'some-name',
      options: FirebaseOptions(
        googleAppID: 'some:id',
        gcmSenderID: 'sender',
        apiKey: 'api-key-goes-here',
        projectID: 'some-id',
      ),
    );
    final _auth = FirebaseAuth.fromApp(_app);
    final _result = await _auth.signInAnonymously();

    setState(() {
      app = _app;
      auth = _auth;
      user = _result.user;
      store = Firestore(app: app); //this is the code that does the magic!
    });
  }

关于服务器端规则配置-参考@cloudwalker的回答

【讨论】:

    【解决方案2】:

    对我来说,这最终成为我如何设置 Firestore 规则的问题。这就是我现在所拥有的,而且效果很好:

    service cloud.firestore {
      match /databases/{database}/documents {
    
    
        match /users/{userId} {
          allow create: if isAuthenticated();
        }
    
        match /users/{userId} {
          allow read, update: if isOwner(userId);
        }
    
        match /users/{userId}/{document=**} {
          allow read, write: if isOwner(userId);
        }
    
        match /categories/{document=**} {
          allow read: if isAuthenticated();
        }
    
        match /config/{document=**} {
            allow read: if isAuthenticated();
        }
    
    
    }
    
    
     function isAuthenticated() {
        return request.auth.uid != null;
      }  
    
      function isOwner(userId) {
        return request.auth.uid == userId;
      }
    }
    

    【讨论】:

    • 这对我有用。这是愚蠢的。来吧,谷歌!感谢您提供它。现在我不会丢弃我的 Firebase 安装并返回 Heroku Postgres——它 100% 的时间都按照规范工作。 (叹气)说真的,谢谢。
    【解决方案3】:

    解决办法是在获得认证用户后初始化FirebaseStorage

    Future<Null> main() async {
      WidgetsFlutterBinding.ensureInitialized();
    
      AppInfo.app = await Firebase.initializeApp(options: AppInfo.firebaseOptions);
    
    }
    

    如果你有一个听众会更容易

    FirebaseAuth.instance.authStateChanges().listen((authUser) async {
    
       if (authUser != null && AppInfo.authUser == null) {
            AppInfo.authUser = authUser;
            print("Got Firebase user: " + authUser.uid);
            setState(() {
              if (AppInfo.instance == null) {          
                AppInfo.instance =
                    FirebaseStorage(app: AppInfo.app, storageBucket: BUCKETGS);
                AppInfo.instanceTemp =
                    FirebaseStorage(app: AppInfo.app, storageBucket: BUCKETTEMP);
              }
    
              AppInfo.userAuthId = authUser.uid;
              streamsStartVerify();
            });
          } else if (authUser == null && AppInfo.authUser != null) {
            print("sign out!!!");
            AppInfo.authUser = null;
            AppInfo.userAuthId = "";
          }
       });
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-21
      • 2019-01-05
      • 2021-05-29
      • 2019-06-17
      • 1970-01-01
      • 2020-06-18
      • 2022-01-11
      • 2020-10-16
      • 2020-11-21
      相关资源
      最近更新 更多