Firebase 資料庫安全性規則 API

規則:類型

。讀

授予客戶端對 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與該使用者帳戶關聯的所有身分的字典。字典的鍵可以是以下任一: emailphonegoogle.comfacebook.comgithub.comtwitter.com 。字典的值是與帳戶關聯的每個身分提供者的唯一識別碼的陣列。例如, auth.token.firebase.identities["google.com"][0]包含與該帳戶關聯的第一個 Google 使用者 ID。
firebase.sign_in_provider用於取得此令牌的登入提供者。可以是以下字串之一: custompasswordphoneanonymousgoogle.comfacebook.comgithub.comtwitter.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取得原始值( stringnumberbooleannull )。

傳回值: ( StringNumberBooleanNull ) - 此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中資料的優先權。

傳回值: ( StringNumberNull ) - 此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 - 如果資料是Booleantrue ;否則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()"