【问题标题】:SImple (and) dirty Firestore authentication rule简单(和)脏 Firestore 身份验证规则
【发布时间】:2019-07-15 10:30:21
【问题描述】:

我在 PHP 项目中使用 REST API 通过 curl (PHP curl) 将数据发送到 Firestore DB。

我一直在努力理解如何为“服务”设置身份验证规则,而通过 Google 授权的建议方法对我来说似乎有些矫枉过正。

我的数据必须可以被 ALL 读取,但只能被我的 PHP 服务器写入。

到目前为止,我可以确保只有在发送的数据集中提供了特定代码 (auth=123) 时才会发生写入操作:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.resource.data.auth==123
      //request.auth.uid != null;
    }
  }
}

问题是,由于每个人都可以读取数据,因此很容易找到该字段(auth)并知道 123 是代码。

两种都可以:

  1. 发送标头(或其他未记录到 DB 数据中的标头)并针对该标头而不是数据字段执行规则检查?

  2. 否则(不太推荐)可能只向用户隐藏“auth”字段?

我知道选项 2 原则上是不可能的,但即使我不知道如何解决,它也可能以某种方式解决。

虽然我知道这不是最好的方法,但它足以保护我的应用程序。

编辑

可能最简单最干净的解决方案是在 Firestore db 中使用一对电子邮件/密码创建一个用户,并在 PHP curl 请求中使用它

我认为我需要在此之后发出 curl 请求:

https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password

然后使用在第一个请求中收到的令牌作为身份验证,通过另一个 PHP curl 发出数据上传

我觉得这是正确的道路,但是....我在第一次请求时遇到了困难

 404. That’s an error.

The requested URL /identitytoolkit/v3/relyingparty/verifyPassword?key=myapiket was not found on this server. That’s all we know.

我觉得我的 curl 请求的形状很糟糕......关于如何正确处理有效负载的任何建议?

解决方案

请参阅下面的步骤和 PHP 代码回答

【问题讨论】:

    标签: rest curl firebase-authentication google-cloud-firestore firebase-security


    【解决方案1】:

    解决方案

    好的,当使用通过 curl PHP 使用的 Firebase Firestore REST API 时,我找到了实现简单但有效的身份验证的解决方案。

    1- 创建一个 Firebase 项目

    2- 就我而言,我需要每个人都能够读取数据,并且只有一个用户能够写入数据。所以在“数据库/规则”中我放了:

    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if request.auth.uid != null;
        }
      }
    }
    

    3- 在“身份验证/登录方法”中启用“电子邮件/密码”作为登录提供程序

    4- 在“身份验证/用户”中,添加用户并提供一对“电子邮件/密码”

    5- 确定您的项目 API 密钥,可在“项目概述/设置/常规/Web API 密钥”中找到

    6- 发出 curl 请求以获取通过用户名和密码验证的 tokenId,并使用此令牌来验证 Firestore 操作。代码如下:

    <?php 
    
    // 1) Retrieve Authorization TOKEN
    // https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password
    $firestore_key = "MY_KEY";
    
    $url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword";
    
    $postfields  = array(
            "email" => 'email@domain.com',
            "password" => 'password123456',
            "returnSecureToken" => true
        );
    
    $datapost = json_encode($postfields);
    
    $curl = curl_init();
    
    curl_setopt_array($curl, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => array('Content-Type: application/json'),
        CURLOPT_URL => $url . '?key='.$firestore_key,
        CURLOPT_USERAGENT => 'cURL',
        CURLOPT_POSTFIELDS => $datapost
    ));
    
    
    $response = curl_exec( $curl );
    
    curl_close( $curl );
    
    $responsJson=json_decode($response,true);
    
    // 2) Add data
    //https://medium.com/@aliuwahab/firestore-firebase-php-saving-data-to-a-firestore-database-using-php-curl-2921da3b0ed4
    
    $ID=10000001;
    
    $firestore_data  = [
            "status" => ["integerValue" => 1500]
        ];
    
    $data = ["fields" => (object)$firestore_data];
    
    //    Possible *value options are:
    //    stringValue
    //    doubleValue
    //    integerValue
    //    booleanValue
    //    arrayValue
    //    bytesValue
    //    geoPointValue
    //    mapValue
    //    nullValue
    //    referenceValue
    //    timestampValue
    
    $json = json_encode($data);
    
    #Provide your firestore project ID Here
    $project_id = "myspecific_project"; //found in "Database/Data"
    
    #Provide your firestore documents group
    $documents_group = "my_group";
    
    // https://stackoverflow.com/questions/50866734/rest-api-firestore-authentication-with-id-token/50866783#50866783
    $url = "https://firestore.googleapis.com/v1beta1/projects/$project_id/databases/(default)/documents/$documents_group/$ID/";
    
    $curl = curl_init();
    
    curl_setopt_array($curl, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => array('Content-Type: application/json',
            'Content-Length: ' . strlen($json),
            'X-HTTP-Method-Override: PATCH',
            'Authorization: Bearer '.$responsJson['idToken']        
            ),
        CURLOPT_URL => $url . '?key='.$firestore_key ,
        CURLOPT_USERAGENT => 'cURL',
        CURLOPT_POSTFIELDS => $json
    ));
    
    
    $response = curl_exec( $curl );
    
    curl_close( $curl );
    
    // Show result
    echo $response . "\n";
    
    ?>
    

    注意:在代码中,我标记了指向帮助我找到有效解决方案的信息的链接

    【讨论】:

    • 你的解决方案拯救了我的一天,伙计!非常感谢。
    【解决方案2】:

    无法随您的请求发送自定义标头。或更准确地说:这些标头在您的安全规则中不可用。请参阅In Firebase Firestore, is there any way to pass info to the Security Rules which is not part of the path?、Accessing Cookies in Google Firestore Rule 和 How to let specific API to run write/read requests on firestore?。

    也不可能通过安全规则隐藏文档的单个字段。用户可以完全访问文档,或者完全无法访问文档。请参阅Firestore: restricting child/field access with security rules 和Securing specific Document fields in Firestore。

    您唯一真正的选择是验证您的 PHP 脚本并将令牌传递给调用,然后验证是您的服务器在进行更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 2021-01-16
      • 2021-05-22
      • 2021-05-27
      • 2021-07-05
      相关资源
      最近更新 更多