規則:類型
。讀
授予客戶端對 Firebase 即時資料庫位置的讀取權限。
.read
規則是一種安全性規則,它授予客戶端對 Firebase 即時資料庫位置的讀取存取權。例如:
".read": "auth != null && auth.provider == 'twitter'"
.read
規則的值是一個字串,它被評估為 JavaScript 表達式語法的子集,並進行了一些行為更改以提高清晰度和正確性。授予讀取位置權限的.read
規則也將允許讀取該位置的任何後代,即使後代有自己的失敗的.read
規則。
.read
規則可以存取除newData
之外的所有 Firebase 即時資料庫規則變數。
。寫
授予客戶端對 Firebase 即時資料庫位置的寫入權限。
.write
規則是一種安全性規則,它授予客戶端對 Firebase 即時資料庫位置的寫入權限。例如:
".write": "auth != null && auth.token.isAdmin == true"
.write
規則的值是一個字串,它被評估為 JavaScript 表達式語法的子集,並進行了一些行為更改以提高清晰度和正確性。授予寫入位置權限的.write
規則也將允許寫入該位置的任何後代,即使後代有自己的失敗的.write
規則。
.write
規則可以存取 Firebase 即時資料庫的所有規則變數。
。證實
在.write
規則授予存取權限後使用,以確保寫入的資料符合特定架構。
一旦.write
規則授予存取權限,就會使用.validate
規則,以確保寫入的資料符合特定標準。除了授予存取權限的.write
之外,所有相關的.validate
規則都必須成功才能允許寫入。例如:
".validate": "newData.hasChildren(['name', 'age'])"
.validate
規則的值是一個字串,它作為 JavaScript 表達式語法的子集進行計算,並進行了一些行為更改以提高清晰度和正確性。
.validate
規則可以存取 Firebase 即時資料庫的所有規則變數。
.indexOn
透過告訴 Firebase 即時資料庫您希望為資料索引哪些鍵來提高查詢效能。
.indexOn
規則告訴 Firebase 即時資料庫伺服器對資料中的特定鍵建立索引,以提高查詢效能。例如,給定一個包含恐龍資料集合的資料庫,我們可以透過添加以下規則告訴 Firebase 即時資料庫在從伺服器返回查詢之前對查詢進行最佳化:
{
"rules": {
"dinosaurs": {
".indexOn": ["height", "length"]
}
}
}
您可以透過參考安全指南中有關為資料建立索引的部分來了解有關.indexOn
規則的更多資訊。
規則:變數
授權
如果用戶端已通過驗證,則包含令牌有效負載的變數;如果用戶端未通過驗證,則包含null
。
Firebase 即時資料庫可讓您輕鬆地向多個內建提供者進行身份驗證,並為它們產生身份驗證令牌。用戶透過內建提供者之一進行身份驗證後,auth 變數將包含以下內容:
場地 | 描述 |
---|---|
provider | 使用的身份驗證方法(例如“密碼”、“匿名”、“facebook”、“github”、“google”或“twitter”)。 |
uid | 唯一的使用者 ID,保證在所有提供者中都是唯一的。 |
token | Firebase 驗證 ID 令牌的內容。請參閱auth.token 。 |
例如,我們可以有以下規則,允許用戶建立評論,只要他們將其用戶 ID 與評論一起儲存即可:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
}
}
}
我們還可以製定以下規則,允許用戶只要使用 Facebook 登入即可建立評論:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && auth.provider == 'facebook'"
}
}
}
授權令牌
包含 Firebase 驗證 ID 令牌內容的變數。
此令牌包含以下部分或全部鍵:
場地 | 描述 |
---|---|
email | 與帳戶關聯的電子郵件地址(如果存在)。 |
email_verified | 如果使用者已驗證他們有權存取email 地址,則為true 。一些提供者會自動驗證他們擁有的電子郵件地址。 |
phone_number | 與帳戶關聯的電話號碼(如果存在)。 |
name | 使用者的顯示名稱(如果已設定)。 |
sub | 用戶的 Firebase UID。這在專案中是獨一無二的。 |
firebase.identities | 與該使用者帳戶關聯的所有身分的字典。字典的鍵可以是以下任一: email 、 phone 、 google.com 、 facebook.com 、 github.com 、 twitter.com 。字典的值是與帳戶關聯的每個身分提供者的唯一識別碼的陣列。例如, auth.token.firebase.identities["google.com"][0] 包含與該帳戶關聯的第一個 Google 使用者 ID。 |
firebase.sign_in_provider | 用於取得此令牌的登入提供者。可以是以下字串之一: custom 、 password 、 phone 、 anonymous 、 google.com 、 facebook.com 、 github.com 、 twitter.com 。 |
firebase.tenant | 與帳戶關聯的tenantId(如果存在)。例如tenant2-m6tyz |
如果使用自訂身份驗證, auth.token
還包含開發人員指定的任何自訂聲明。
所有這些值都可以在規則內使用。例如,要限制與 gmail.com 地址關聯的 Google 帳戶的訪問,我們可以新增規則:
{
"rules": {
".read": "auth != null",
"gmailUsers": {
"$uid": {
".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
}
}
}
}
為了完整起見, auth.token
中還包含以下字段,但它們不太可能對規則有用。
場地 | 描述 |
---|---|
iss | 代幣的發行者。 |
aud | 代幣的受眾。 |
auth_time | 使用者上次使用接收令牌的設備透過憑證進行身份驗證的時間。 |
iat | 令牌發行的時間。 |
exp | 令牌過期的時間。 |
$地點
一個變量,可用於引用先前在規則結構中使用的$location
的鍵。
當規則結構中有$location
時,您可以在規則運算式中使用符合的$
變數來取得正在讀取或寫入的實際子項的名稱。因此,假設我們希望為每個使用者提供其自己的/users/<user>
位置的讀寫存取權。我們可以使用:
{
"rules": {
"users": {
"$user": {
".read": "auth.uid === $user",
".write": "auth.uid === $user"
}
}
}
}
當客戶端嘗試存取/users/barney
時, $user
預設位置將與$user
等於「barney」相符。因此.read
規則將檢查auth.uid === 'barney'
是否。因此,只有當客戶端透過 uid 為「barney」進行身份驗證時,讀取
才會成功。/users/barney
現在
根據 Firebase 即時資料庫伺服器,包含自 Unix 紀元以來的毫秒數。
now
變數包含根據 Firebase 即時資料庫伺服器的 UNIX 紀元以來的毫秒數。例如,您可以使用它來驗證使用者的created
時間從未設定為將來的時間:
{
"rules": {
"users": {
"$user": {
"created": {
".validate": "newData.val() < now"
}
}
}
}
}
根
與 Firebase 即時資料庫根目錄中的目前資料相對應的RuleDataSnapshot 。
root 變數為您提供與 Firebase 即時資料庫根目錄中的目前資料相對應的RuleDataSnapshot 。您可以使用它來讀取規則表達式中資料庫中的任何資料。例如,如果我們希望僅當使用者的/users/<id>/active
設定為 true 時才允許使用者讀取/comments
,我們可以使用:
{
"rules": {
"comments": {
".read": "root.child('users').child(auth.uid).child('active').val() == true"
}
}
}
然後,如果/users/barney/active
包含值 true,則使用 uid 為「barney」進行身份驗證的使用者可以寫入/comments
節點。
數據
與 Firebase 即時資料庫中目前執行規則位置的目前資料相對應的RuleDataSnapshot 。
data 變數為您提供與目前執行規則的資料庫位置中的目前資料相對應的RuleDataSnapshot (與 root 不同,root 為您提供資料庫根的資料)。
例如,如果您想要讓任何客戶端存取/users/<user>
(如果/users/<user>/public
設定為 true),您可以使用:
{
"rules": {
"users": {
"$user": {
".read": "data.child('public').val() == true"
}
}
}
}
data 變數在.read
、 .write
和.validate
規則中可用。
新數據
與允許寫入時產生的資料相對應的RuleDataSnapshot 。
對於.write
和.validate
規則,newData 變數為您提供一個與允許寫入時將產生的資料相對應的RuleDataSnapshot (它是現有資料與正在寫入的新資料的「合併」)。因此,如果您想確保每個用戶都有姓名和年齡,您可以使用:
{
"rules": {
"users": {
"$user": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['name', 'age'])"
}
}
}
}
由於 newData 合併了現有數據和新數據,因此即使對於「部分」更新,它也能正常運作。例如:
var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();
newData 變數在.read
規則中不可用,因為沒有寫入新資料。你應該只使用數據。
RuleDataSnapshot:方法
值()
從此RuleDataSnapshot取得原始值( string
、 number
、 boolean
或null
)。
傳回值: ( String
、 Number
、 Boolean
、 Null
) - 此RuleDataSnapshot中的原始值。
與DataSnapshot.val()
不同,在具有子資料的 RuleDataSnapshot 上呼叫val()
將不會傳回包含子資料的物件。相反,它將傳回一個特殊的哨兵值。這確保了規則始終能夠非常有效地運作。
因此,您必須始終使用child()
來存取子層級(例如data.child('name').val()
,而不是data.val().name
)。
僅當 isReadable 子項在正在讀取的位置設為 true 時,此範例才允許讀取。
".read": "data.child('isReadable').val() == true"
孩子()
取得指定相對路徑位置的RuleDataSnapshot 。
參數: childPath
String
- 子資料位置的相對路徑。
傳回值: RuleDataSnapshot
- 子位置的RuleDataSnapshot 。
相對路徑可以是簡單的子名稱(例如“fred”),也可以是更深的斜線分隔路徑(例如“fred/name/first”)。如果子位置沒有數據,則傳回空的 RuleDataSnapshot。
僅當 isReadable 子項在正在讀取的位置設為 true 時,此範例才允許讀取。
".read": "data.child('isReadable').val() == true"
父級()
取得父親位置的RuleDataSnapshot 。
傳回值: RuleDataSnapshot
- 父親位置的RuleDataSnapshot 。
如果此實例引用 Firebase 實時資料庫的根,則它沒有父級, parent()
將失敗,導致當前規則表達式被跳過(作為失敗)。
僅當 isReadable 同級設定為 true 時,此範例才允許讀取。
".read": "data.parent().child('isReadable').val() == true"
hasChild(子路徑)
如果指定的子項存在,則傳回 true。
參數: childPath
String
- 潛在子項位置的相對路徑。
傳回值: Boolean - 如果資料存在於指定的子路徑中, true
;否則false
。
此範例僅允許寫入包含子「名稱」的資料。
".validate": "newData.hasChild('name')"
有孩子([孩子])
檢查兒童是否存在。
參數: children
Array
可選- 必須全部存在的子鍵數組。
傳回值: Boolean
值 - 如果(指定的)子項存在則為true
;否則false
。
如果未提供參數,如果RuleDataSnapshot有任何子項,它將傳回 true。如果提供了子名稱數組,則僅當所有指定的子名稱都存在於RuleDataSnapshot中時才會傳回 true。
此範例僅允許寫入包含一個或多個子項的資料。
".validate": "newData.hasChildren()"
此範例僅允許寫入包含“name”和“age”子項目的資料。
".validate": "newData.hasChildren(['name', 'age'])"
存在()
如果此RuleDataSnapshot包含任何數據,則傳回 true。
傳回值: Boolean
- 如果RuleDataSnapshot包含任何數據, true
;否則false
。
如果此RuleDataSnapshot包含任何數據,則exists 函數將傳回true。它純粹是便利函數,因為data.exists()
相當於data.val() != null
。
只要沒有現有數據,此範例就允許在此位置進行寫入。
".write": "!data.exists()"
取得優先權()
取得RuleDataSnapshot中資料的優先權。
傳回值: ( String
、 Number
、 Null
) - 此RuleDataSnapshot中資料的優先權。
此範例確保正在寫入的新資料具有優先級
".validate": "newData.getPriority() != null"
isNumber()
如果此RuleDataSnapshot包含數值,則傳回 true。
傳回值: Boolean
值 - 如果資料是數字,則為true
;否則false
。
此範例確保寫入的新資料具有帶有數值的子「age」。
".validate": "newData.child('age').isNumber()"
isString()
如果此RuleDataSnapshot包含字串值,則傳回 true。
傳回值: Boolean
- 如果資料是String
true
;否則false
。
此範例確保寫入的新資料具有帶有字串值的子「name」。
".validate": "newData.child('name').isString()
是布林值()
如果此RuleDataSnapshot包含布林值,則傳回 true。
傳回值: Boolean
- 如果資料是Boolean
, true
;否則false
。
此範例確保寫入的新資料具有帶有布林值的子「active」。
".validate": "newData.child('active').isBoolean()"
字串:屬性
長度
傳回字串的長度。
傳回值: Number
- 字串中的字元數。
此範例要求字串至少包含 10 個字元。
".validate": "newData.isString() && newData.val().length >= 10"
字串:方法
包含(子字串)
如果字串包含指定的子字串,則傳回 true。
參數: substring
String
- 要尋找的子字串。
傳回值: Boolean
- 如果字串包含指定的子字串, true
;否則false
。
此範例要求資料是包含“@”的字串。
".validate": "newData.isString() && newData.val().contains('@')"
開始於(子字串)
如果字串以指定的子字串開頭,則傳回 true。
參數: substring
String
- 在開頭尋找的子字串。
傳回值: Boolean
- 如果字串包含指定的子字串, true
;否則false
。
如果auth.token.identifier
以「internal-」開頭,則此範例允許讀取訪問
".read": "auth.token.identifier.beginsWith('internal-')"
以(子字串)結尾
如果字串以指定的子字串結尾,則傳回 true。
參數: substring
String
- 在結尾尋找的子字串。
傳回值: Boolean
- 如果字串以指定子字串結尾則為true
;否則false
。
如果auth.token.identifier
以“@company.com”結尾,則此範例允許讀取訪問
".read": "auth.token.identifier.endsWith('@company.com')"
替換(子字串,替換)
傳回字串的副本,其中指定子字串的所有實例都替換為指定的替換字串。
參數: substring String
- 要尋找的子字串。 replacement String
- 用於替換子字串的字串。
傳回值: String
- 用 replacement 取代 substring 後的新字串。
replace()
方法與 JavaScript replace()
方法略有不同,因為它用指定的替換字串替換指定子字串的所有實例,而不僅僅是第一個實例。
由於鍵中不允許使用句點,因此我們需要在儲存字串之前使用句點對字串進行轉義。電子郵件地址就是一個例子。假設我們的/whitelist/
節點中有一個列入白名單的電子郵件地址清單:
{
"user": {
"$uid": {
"email": <email>
}
},
"whitelist": {
"fred@gmail%2Ecom": true,
"barney@aol%2Ecom": true
}
}
我們可以製定一條規則,僅允許新增使用者的電子郵件地址位於/whitelist/
節點中:
{
"rules": {
"users": {
"$uid": {
".read": "true",
".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
}
}
}
}
toLowerCase()
傳回轉換為小寫的字串的副本。
傳回值: String
- 轉換為小寫的字串。
如果/users
下存在全小寫的auth.token.identifier
,則此範例允許讀取存取。
".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"
toUpperCase()
傳回轉換為大寫的字串的副本。
傳回值: String
- 轉換為大寫的字串。
如果/users
下存在全部大寫的auth.token.identifier
,則此範例允許讀取存取。
".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"
匹配(正規表示式)
如果字串與指定的正規表示式文字匹配,則傳回 true。
傳回值: Boolean
值 - 如果字串與正規表示式文字 regex 匹配, true
;否則false
。
請參閱完整規則正規表示式文件。
營運商
+(新增)
用於新增變數或用於字串連接。
以下範例確保新值將現有值恰好增加 1。這對於實作計數器很有用:
".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"
-(求負或減)
用於對規則表達式中的某個值求反或減去兩個值。
此驗證規則檢查新值是否為以下位置的子值的倒數:
".validate": "newData.val() === -(data.child('quantity').val())"
以下範例使用減法來確保只能讀取最近十分鐘的訊息:
".read": "newData.child('timestamp').val() > (now - 600000)"
*(乘法)
用於在規則表達式中乘以變數。
此驗證規則檢查新值是否等於價格和數量的乘積(兩個現有值):
".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"
/(除)
用於劃分規則表達式中的變數。
在以下範例中,驗證規則可確保儲存的資料是其他地方儲存的總資料的平均值:
".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"
%(模數)
用於找出規則表達式中一個變數除以另一個變數的餘數。
此規則驗證只能寫入偶數:
".validate": "newData.val() % 2 === 0"
===(等於)
用於檢查規則表達式中的兩個變數是否具有相同的類型和值。
以下規則使用 === 運算子僅向使用者帳戶的擁有者授予寫入存取權限。使用者的 uid 必須與鍵 ( $user_id
) 完全匹配,規則才能評估為 true。
"users": {
".write": "$user_id === auth.uid"
}
!==(不等於)
用於檢查規則表達式中的兩個變數是否不相等。
以下讀取規則可確保只有登入使用者才能讀取資料:
".read": "auth !== null"
&& (和)
如果兩個操作數都為 true,則計算結果為 true。用於評估規則表達式中的多個條件。
以下驗證規則檢查新資料是否為少於 100 個字元的字串:
".validate": "newData.isString() && newData.val().length < 100"
|| (或)
如果規則表達式中的一個操作數為 true,則計算結果為 true。
在這個例子中,只要舊資料或新資料不存在,我們就可以寫入。換句話說,如果我們要刪除或建立數據,但不能更新數據,則可以寫入。
".write": "!data.exists() || !newData.exists()"
! (不是)
如果其單一操作數為 false,則計算結果為 true。在規則表達式中,!運算符通常用於查看資料是否已寫入某個位置。
以下規則僅在指定位置沒有資料時允許寫入存取:
".write": "!data.exists()"
>(大於)
用於檢查規則表達式中的一個值是否大於另一個值。
此驗證規則檢查寫入的字串不是空字串:
".validate": "newData.isString() && newData.val().length > 0"
<(小於)
用於檢查規則表達式中的一個值是否小於另一個值。
此驗證規則檢查字串是否少於 20 個字元:
".validate": "newData.isString() && newData.val().length < 20"
>=(大於或等於)
用於檢查規則表達式中的一個值是否大於或等於另一個值。
此驗證規則檢查寫入的字串不是空字串:
".validate": "newData.isString() && newData.val().length >= 1"
<=(小於或等於)
用於檢查規則表達式中的一個值是否小於或等於另一個值。
此驗證規則可確保未來無法新增資料:
".validate": "newData.val() <= now"
? (三元運算子)
用於評估條件規則表達式。
三元運算子採用三個運算元。 ? 之前的操作數是條件。如果條件計算結果為 true,則計算第二個操作數。如果條件為假,則計算第三個操作數。
對於以下驗證規則,新值可以是數字或布林值。如果是數字,則必須大於 0。
".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"