【问题标题】:INTERMITTENT FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions间歇性 FirebaseFirestoreException:PERMISSION_DENIED:权限缺失或不足
【发布时间】:2019-03-28 12:30:05
【问题描述】:

我有一个带有 PeriodicWork 的 android 应用程序,它每 30 分钟将数据写入 Firestore。它工作正常,但我注意到在某些情况下,它会失败,但 FirebaseFirestoreException: PERMISSION_DENIED 除外。我不明白为什么它会抱怨权限,如果它可以将数据写入 Firestore。

// Firestore Rules
service cloud.firestore {
  match /databases/{database}/documents {

    match /bar/{document=**} {
      allow read: if true;
      allow create: if true;
    }

  }
}
// Write to Firestore
val firebaseFirestore = FirebaseFirestore.getInstance()

firebaseFirestore.collection(BAR_KEY)
        .add(barData)
        .addOnSuccessListener { /*success callback*/ }
        .addOnFailureListener { e ->
            Crashlytics.log(e.message)
            Crashlytics.logException(e)
            /* failure callback */
        }
Non-fatal Exception: com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
       at com.google.firebase.firestore.util.Util.exceptionFromStatus(com.google.firebase:firebase-firestore@@18.1.0:119)
       at com.google.firebase.firestore.core.SyncEngine.notifyUser(com.google.firebase:firebase-firestore@@18.1.0:446)
       at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(com.google.firebase:firebase-firestore@@18.1.0:430)
       at com.google.firebase.firestore.core.FirestoreClient.handleRejectedWrite(com.google.firebase:firebase-firestore@@18.1.0:275)
       at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(com.google.firebase:firebase-firestore@@18.1.0:707)
       at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(com.google.firebase:firebase-firestore@@18.1.0:663)
       at com.google.firebase.firestore.remote.RemoteStore.access$600(com.google.firebase:firebase-firestore@@18.1.0:53)
       at com.google.firebase.firestore.remote.RemoteStore$2.onClose(com.google.firebase:firebase-firestore@@18.1.0:206)
       at com.google.firebase.firestore.remote.AbstractStream.close(com.google.firebase:firebase-firestore@@18.1.0:334)
       at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(com.google.firebase:firebase-firestore@@18.1.0:388)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3(com.google.firebase:firebase-firestore@@18.1.0:149)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$Lambda$4.run(Unknown Source:4)
       at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(com.google.firebase:firebase-firestore@@18.1.0:67)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(com.google.firebase:firebase-firestore@@18.1.0:135)
       at com.google.firebase.firestore.util.FirestoreChannel$1.onClose(com.google.firebase:firebase-firestore@@18.1.0:161)
       at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
       at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
       at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
       at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:678)
       at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
       at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
       at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
       at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:397)
       at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:459)
       at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:63)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:546)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$600(ClientCallImpl.java:467)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:584)
       at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
       at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at com.google.firebase.firestore.util.AsyncQueue$DelayedStartFactory.run(com.google.firebase:firebase-firestore@@18.1.0:205)
       at java.lang.Thread.run(Thread.java:764)
Caused by io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
       at io.grpc.Status.asException(Status.java:534)
       at com.google.firebase.firestore.util.Util.exceptionFromStatus(com.google.firebase:firebase-firestore@@18.1.0:117)
       at com.google.firebase.firestore.core.SyncEngine.notifyUser(com.google.firebase:firebase-firestore@@18.1.0:446)
       at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(com.google.firebase:firebase-firestore@@18.1.0:430)
       at com.google.firebase.firestore.core.FirestoreClient.handleRejectedWrite(com.google.firebase:firebase-firestore@@18.1.0:275)
       at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(com.google.firebase:firebase-firestore@@18.1.0:707)
       at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(com.google.firebase:firebase-firestore@@18.1.0:663)
       at com.google.firebase.firestore.remote.RemoteStore.access$600(com.google.firebase:firebase-firestore@@18.1.0:53)
       at com.google.firebase.firestore.remote.RemoteStore$2.onClose(com.google.firebase:firebase-firestore@@18.1.0:206)
       at com.google.firebase.firestore.remote.AbstractStream.close(com.google.firebase:firebase-firestore@@18.1.0:334)
       at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(com.google.firebase:firebase-firestore@@18.1.0:388)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3(com.google.firebase:firebase-firestore@@18.1.0:149)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$Lambda$4.run(Unknown Source:4)
       at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(com.google.firebase:firebase-firestore@@18.1.0:67)
       at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(com.google.firebase:firebase-firestore@@18.1.0:135)
       at com.google.firebase.firestore.util.FirestoreChannel$1.onClose(com.google.firebase:firebase-firestore@@18.1.0:161)
       at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
       at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
       at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
       at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:678)
       at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
       at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
       at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
       at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:397)
       at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:459)
       at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:63)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:546)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$600(ClientCallImpl.java:467)
       at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:584)
       at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
       at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at com.google.firebase.firestore.util.AsyncQueue$DelayedStartFactory.run(com.google.firebase:firebase-firestore@@18.1.0:205)
       at java.lang.Thread.run(Thread.java:764)

【问题讨论】:

  • 您的规则允许创建数据,但不允许更新数据,这让我认为问题是由对现有文档的更新引起的。您显示的错误都以 Firestore 的内部代码开始和结束。您是否有指向您自己的导致异常的实际代码行的堆栈跟踪?
  • 嗨@FrankvanPuffelen,感谢您的回复。异常从.addOnFailureListener { e -> Crashlytics.log(e.message) Crashlytics.logException(e) } 记录。我只想允许创建数据而不是更新它,我需要声明更新规则吗?另外,生成的文档 ID 是否可能已经存在并且尝试创建数据导致了问题?
  • 据我所知,add() 应该只触发一次写入。 :-/

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


【解决方案1】:

当您再次尝试更新同一个文档时,它会失败。

将 add(barData) 更改为 set(barData, SetOptions.merge())

并在您的安全规则中添加以下行

allow update: if true;

【讨论】:

  • 感谢您的回答。我正在尝试创建不更新的数据。
  • 然后在规则中声明允许删除和更新。它会工作
  • 我想了解问题背后的原因。从技术上讲,我不想允许删除和更新。我这样做的目的是某种历史记录,因此一旦创建了数据,除了读取它之外,您无法对其进行任何操作。
  • 基本上读写有两条规则。我们可以通过三种方式定义 Write(创建、更新、删除)。如果您只想允许创建,则将 create 设置为 true 并更新,将 delete 设置为 false。定义创建时,必须定义更新和删除规则。
猜你喜欢
  • 2021-12-31
  • 2019-10-24
  • 2018-09-12
  • 2020-10-14
  • 2018-03-17
  • 2020-09-25
  • 2020-10-01
相关资源
最近更新 更多