首页 > 解决方案 > 如何为匿名用户设置 Firebase 规则以仅读取和写入自己的数据

问题描述

我希望匿名用户只能读取和写入他们自己的数据。我将以下内容作为我的安全规则,但在模拟器和应用程序中出现无法读取错误。

我不确定我是否以正确的方式去做。我的主要目标是将同一用户的新评估嵌套在他们的 uid 下,并使其只能读取、写入和更新自己的评估。

{
  "rules": {
    "users": {
      "$uid": {
          ".write": "$uid === auth.uid";
           ".read": "$uid === auth.uid";  
      }
    }
  }
}

这是我的分支目前的样子

https://i.stack.imgur.com/u4DEI.png

这就是我认为完成我需要的事情的样子。 理想的数据库结构

auth.gaurd.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from "../../shared/service/auth.service";
import { Observable } from 'rxjs';
import * as firebase from 'firebase';
@Injectable({
  providedIn: 'root'
})

export class AuthGuard implements CanActivate {
  
  uid: string;
  constructor(
    public authService: AuthService,
    public router: Router
  ){ }

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    this.authStateListener();
    return true;
  }
  authStateListener() {
    // [START auth_state_listener]
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        // User is signed in, see docs for a list of available properties
        this.uid = user.uid;
        console.log("user"+user.isAnonymous)
        console.log("uid"+this.uid)
      } else {
        // User is signed out
        return  firebase.auth().signOut().then(() => {
          localStorage.removeItem('user');
          this.router.navigate(['sign-in']);
        })
      }
    });

}
}

auth.service.ts

import { Injectable, NgZone, ViewChild, ElementRef, Component } from '@angular/core';
import { User } from "../service/user";
import { auth } from 'firebase/app';
import { AngularFireAuth } from "@angular/fire/auth";
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { ActivatedRoute, Router } from "@angular/router"; 
import * as firebase from 'firebase';
import "firebase/auth";


@Injectable({
  providedIn: 'root'
})



export class AuthService {
  userData: any; // Save logged in user data
 @ViewChild('btnLogin') btnLogin: HTMLButtonElement;


  constructor(
    public afs: AngularFirestore,   // Inject Firestore service
    public afAuth: AngularFireAuth, // Inject Firebase auth service
    public router: Router,
    private actRoute: ActivatedRoute,
    public ngZone: NgZone // NgZone service to remove outside scope warning
    
  ) {
    

  }

  anonymousSignIn(){
    firebase.auth().signInAnonymously()
    .then(()=>{
      this.router.navigate(['assessment']);
      console.log("clicking")
    }).catch((error) => {
      var errorCode = error.code;

      var errorMessage = error.message;
      console.log("error here")
    });
  }

**这是在 Firebase 中推送、读取、更新和删除分支的代码。ReadAssessment 列表应显示匿名用户拥有的所有数据,以便他们阅读。** 火灾评估.service.ts

import { AuthGuard } from './../shared/guard/auth.guard';
import { Injectable } from '@angular/core';
import {AngularFireDatabase, AngularFireList,  AngularFireObject} from '@angular/fire/database';
import * as firebase from 'firebase';
import {Business} from '../models/business';
import { ActivatedRoute, Router } from '@angular/router';
import { map } from 'rxjs/internal/operators/map';
import { isNgTemplate } from '@angular/compiler';



@Injectable({
  providedIn: 'root'
})
export class FireAssessmentService {
  assessmentsRef: AngularFireList<any>; // Reference to Assessment data list, its an Observable
  assessmentRef: AngularFireObject<any>; // Reference to assessment object
  public database = firebase.database();
  public UserAssessmentInput;
  public ref;
  public actRoute: ActivatedRoute;
  public router: Router;
  public auth: AuthGuard;
  
  


  constructor(private db: AngularFireDatabase) {
   
   }
CreateAssessment(business: Business ){
  const key = this.database.ref('/users').push().key;
  this.database.ref('/users').child(key).set(
    ///this.assessmentsRef.ref('/users').push(
    {
      busiName: business.busiName
       });
    
  }
  
  
  ReadAssessment(id: string){
    this.assessmentRef = this.db.object('users/' + id);
    return this.assessmentRef;
  }
  
  
  ReadAssessmentsList(){
    this.assessmentsRef = this.db.list('users/');
    return this.assessmentsRef;
  }
  
   UpdateAssessments (business: Business){
    this.assessmentRef.update({
    busiName: business.busiName
      });
  }
  
  DeleteAssessment(){
    this.assessmentRef = this.db.object('users/');
    this.assessmentRef.remove();
  }

商业.ts

export interface Business {
    $key: string;
    busiName: string;
    
    }

标签: javascriptfirebase-realtime-databasefirebase-authenticationfirebase-securityangularfire2

解决方案


现在你正在用这个创建数据:

const key = this.database.ref('/users').push().key;
this.database.ref('/users').child(key).set({
  busiName: business.busiName
});

当您调用Firebase 时,会生成一个新的唯一位置,该位置是以JSONpush()开头的键。-M...

该值不是当前用户的 UID,因此这些规则不允许用户读取或写入它:

"users": {
  "$uid": {
      ".write": "$uid === auth.uid";
       ".read": "$uid === auth.uid";  
  }
}

相反,您应该使用用户的 UID 作为键将数据写入节点下。那看起来像:

const key = this.database.ref('/users').push().key;
if (firebase.auth().currentUser) {
  const key = firebase.auth().currentUser.uid;
  this.database.ref('/users').child(key).set({
    busiName: business.busiName
  });
}
else {
  console.error("No current user while trying to write business name");
}

推荐阅读