3

我正在用AngularJS構建一個簡單的Firebase應用程序。這個應用程序通過谷歌認證用戶。每個用戶都有一個書目清單。任何人都可以看書,即使他們沒有被認證。只有一本書的創建者才能編輯它。然而,即使其他人添加了書籍,個人用戶也需要能夠記錄他們已經閱讀過書籍。瞭解Firebase關於用戶寫入,全局讀取的規則

我有rules.json像這樣:

{ 
    "rules": { 
    ".read": false, 
    ".write": false, 
    "book": { 
     "$uid": { 
     ".write": "auth !== null && auth.uid === $uid", 
     } 
     ".read": true, 
    } 
    } 
} 

,我試圖用簡單的寫了一本書:

$firebaseArray(new Firebase(URL + "/book")).$add({foo: "bar"}) 

我在嘗試這樣做,雖然我當拒絕「權限」錯誤似乎能夠在Forge中手動創建的圖書read

我也認爲存儲讀者的最佳方式是使其成爲本書的一個屬性(登錄讀取器的一組$uid)。 ".write"好像會阻止這個,所以我該怎麼做?

"$uid": { 
    ".write": "auth !== null && auth.uid === $uid", 
    "readers": { 
    ".write": "auth !== null" 
    } 
}, 

這似乎是一個驗證規則是適當的在這裏也...像newData.val() == auth.uid,但我不知道如何驗證readers應該是一個數組(或專門一組)這些值。

+0

據我看到你的'.read'規則是正確的,因爲你的'ref'是'/ book'節點。但是我不明白你想要'.write'的功能。請注意,'$ add'會生成一個所謂的push-id,它與'$ uid'不一樣。看起來你更有可能擁有'/ book/$ bookid', 'creator'具有創作者的「uid」。然後,您可以將'book/$ bookid/.write'設置爲'auth!= null &&(!data.exists()|| auth.uid == data.child('creator')。val())''。 –

+0

@FrankvanPuffelen是''$ bookid「'不同於'」$ uid「'?我應該創建一個像「book/$ bookid」或嵌套的「book」和「$ bookid」''''$ uid「'規則的規則(或者沒關係) –

+0

任何以' $'只是一個變量,它可以有任何名稱。但'$ uid'通常用於「user id」節點,所以由'auth.uid'標識的節點。由於您正在通過'$ add'添加書籍,因此它們通過推送ID進行標識。 –

回答

7

讓我們先從一個樣本JSON片段:

"book": { 
    "-JRHTHaIs-jNPLXOQivY": { //this is the generated unique id 
     "title": "Structuring Data", 
     "url": "https://www.firebase.com/docs/web/guide/structuring-data.html", 
     "creator": "twiter:4916627" 

    }, 
    "-JRHTHaKuITFIhnj02kE": { 
     "title": "Securing Your Data", 
     "url": "https://www.firebase.com/docs/security/guide/securing-data.html", 
     "creator": "twiter:209103" 
    } 
    } 

所以這是兩個鏈接到文章的列表。每個鏈接都由不同的用戶添加,該用戶由creator標識。 creator的值是uid,它是Firebase身份驗證提供的值,可在您的安全規則auth.uid下使用。因爲我看到你的.read規則是正確的,因爲你的裁判是到/ book節點就

{ 
    "rules": { 
    ".read": false, 
    "book": { 
     ".read": true, 
    } 
    } 
} 

我將您的規則拆分成兩個部分在這裏。

$firebaseArray(new Firebase(URL + "/book")) 

請注意,由於您沒有對頂層節點的讀取訪問權限,因此下面的ref不起作用。

$firebaseArray(new Firebase(URL)) 

現在爲.write規則。首先,您需要爲book級別授予用戶寫入訪問權限。調用$add意味着您要添加該級別下的節點,因此需要寫入訪問權限。

{ 
    "rules": { 
    "book": { 
     ".write": "auth != null" 
    } 
    } 
} 

我離開.read規則在這裏的清晰度。

這允許任何經過身份驗證的用戶寫入書籍節點。這意味着他們可以添加新書(您想要的)並更改現有書(您不需要)。

你最後的要求是最棘手的。任何用戶都可以添加一本書。但是一旦有人添加了一本書,只有那個人可以修改它。在火力地堡的安全規則,你會模型,如:

{ 
    "rules": { 
    "book": { 
     ".write": "auth != null", 
     "$bookid": { 
     ".write": "!data.exists() || auth.uid == data.child('creator').val()" 
     } 
    } 
    } 
} 

在最後這個規則,我們允許特定本書的寫作要麼有在此位置沒有當前數據(即它是一個新的書)或者數據是由當前用戶創建的。

在上面的例子中,$bookid只是一個變量名。重要的是,它下面的規則適用於每本書。如果需要,我們可以在我們的規則中使用$bookid,它將分別持有-JRHTHaIs-jNPLXOQivY-JRHTHaKuITFIhnj02kE。但在這種情況下,這不是必需的。

+0

我還沒有真正設法測試它,但是在'$ bookid'下我有讀者:{「.write」:「auth!== null」}' - 這應該允許任何用戶寫入讀者的財產,對吧? –

+2

它看起來不錯,但如果沒有完全看到就很難確定。將數據嵌套到不同的安全約束通常會導致頭痛。我會把讀者放入一個單獨的頂級'book_readers'節點,所以'/ book_readers/$ bookid/$ readerid'。這樣你可以隔離讀者的安全規則。請參閱關於「避免嵌套數據」的文檔部分:https://www.firebase.com/docs/web/guide/structuring-data.html#section-denormalizing-data –

2

首先關閉「權限被拒絕」錯誤。您正在嘗試在「book」節點中直接寫入,而不是「book/$ uid」,因此出現此錯誤。你現在做什麼

例子:

"book": { 
    "-JRHTHaIs-jNPLXOQivY": { //this is the generated unique id 
     "foo": "bar" 
    }, 
    "-JRHTHaKuITFIhnj02kE": { 
     "foo": "bar" 
    } 
    } 

在你的規則,你有寫集合全局規則爲false,這樣會默認和旁邊所做的特定節點的規則書/ $ UID。因此,當試圖直接在「book」中編寫時,它會將默認規則設置爲false。有關Firebase規則的更多信息,請參閱Securing your data

對於問題的最後部分,我建議你看看Structuring data以獲取有關在Firebase中構建數據的最佳方法的更多信息。

因此,您應該好好看看您想要在Firebase中保存和寫入的內容,並確保您的規則的結構相應。

+0

如果我理解正確,'。add'不會直接寫入'book'節點,而是會使用'$ uid'寫入子節點。我想我只需要改變寫入規則。我不認爲我的建議結構有問題,因爲如果用戶閱讀了一本書,它只是記錄 - 我只是想確保所寫的內容是一個有效的,唯一的用戶。 –

+0

發生了什麼事情是這樣的:$ add使用push()函數創建一個唯一的id。 $ uid是用戶標識。 –

+0

@ExplosionPills我剛剛給我的答案添加了一個例子。 –