服务器端访问Firestore和安全规则:Firestore客户端已关闭



我在Firestore中有数据,我每天用服务器端Java代码更新这些数据。这已经持续了几个月,没有出现任何问题。我创建Firestore实例的方式如下。(我在Firestore中有一个服务帐户,它的凭据在json文件中。(

GoogleCredentials myCredentials = GoogleCredentials.fromStream(new FileInputStream("/myPath/myCredentials.json"));  

FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance()
.toBuilder()
.setProjectId("myFirestoreProject")
.setCredentials(myCredentials)
.build();
Firestore db = firestoreOptions.getService();

Firestore安全规则并不是一个问题,因为客户端还没有访问Firestore的权限,所以我已经无条件地打开了所有涉及的Firestore集合以进行读写操作。现在,由于我只希望从myCredentials.json中的凭据创建的对Firestore的服务器端访问具有写入权限,因此我将Firestore安全规则设置如下。

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /myCollection/{document=**}{
allow read;
allow write: if false;
}
}         
}

然而,这些规则会阻止我访问上面创建的Firestore,而且我也不知道如何设置适当的规则。我知道,如果Firestore实例是由创建的,那么可以绕过任何Firestore安全规则

FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(myCredentials)
.setDatabaseUrl("https://myFirestoreProject.firebaseio.com")
.build();

FirebaseApp app = FirebaseApp.initializeApp(options, "myFirestoreApp");
Firestore db = FirestoreClient.getFirestore(app);

现在,当我创建这样的数据库并运行更新代码时,我会收到错误消息

java.lang.IllegalStateException: Firestore client has already been closed

我不会在这里发布精确的更新代码,因为它一方面很长,另一方面在创建Firestore实例的第一种类型时运行平稳。然而,更简单的玩具代码运行得很好,所以我检查了第二种类型的Firestore创建是否确实绕过了安全规则。

我使用NetBeans,在上述两种情况下,maven导入如下:

<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>8.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>7.1.1</version>
</dependency>
</dependencies>>

对这两个Firestore实例之间的差异的困惑让我产生了两个问题:

  1. 如果我使用Firestore的初始创建,我是否可以设置安全规则,以便授予此Firestore实例写入权限,同时阻止任何客户端写入访问,例如从Android应用程序?

  2. 上面关于第二次创建Firestore的错误消息的常见原因是什么?有没有办法防止Firestore客户端关闭?

回答您的第一个问题,如文档中的注释所述:

"服务器客户端库绕过所有Cloud Firestore安全规则,而是通过Google应用程序默认凭据进行身份验证。如果您正在使用服务器客户端库或REST或RPC API,请确保为Cloud Firestore设置身份和访问管理(IAM(">

因此,这些规则只适用于客户端。您可以通过拒绝对数据库的所有访问来拒绝所有客户端访问。

至于第二个问题,请检查您的代码是否多次初始化或关闭数据库,并确保它遵循文档中的示例。

如果我通过创建Firestore实例

FirestoreOptions firestoreOptions = FirestoreOptions.newBuilder()
.setCredentials(myCredentials)
.setProjectId("myFirestoreProject")
.build();


Firestore db = firestoreOptions.getService();

,绕过了安全规则,并且在写入所有数据之前,此实例不会关闭。

最新更新