規則:類型
.read
可授予用戶端 Firebase 即時資料庫位置的讀取權限。
.read
規則是一種安全性規則,可授予用戶端 Firebase 即時資料庫位置的讀取權限。例如:
".read": "auth != null && auth.provider == 'twitter'"
.read
規則的值是字串,系統會將其評估為 JavaScript 運算式語法的子集,但會進行一些行為變更,以提高清晰度和正確性。授予位置讀取權限的 .read
規則也會允許讀取該位置的所有子系,即使子係有自己的 .read
規則失敗也一樣。
.read
規則可以存取所有 Firebase 即時資料庫的規則變數,但 newData
除外。
.write
可授予用戶端 Firebase 即時資料庫位置的寫入權限。
.write
規則是一種安全性規則,可授予用戶端寫入 Firebase 即時資料庫位置的權限。例如:
".write": "auth != null && auth.token.isAdmin == true"
.write
規則的值是字串,系統會將其評估為 JavaScript 運算式語法的子集,但會進行一些行為變更,以提高清晰度和正確性。授予某位置寫入權限的 .write
規則,也會允許寫入該位置的所有子系,即使子係有自己的 .write
規則而失敗也一樣。
.write
規則可存取所有 Firebase 即時資料庫的規則變數。
.validate
在 .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
規則,請參閱安全性指南中「建立資料索引」一節。
規則:變數
auth
包含權杖酬載的變數 (如果用戶端已通過驗證);或 null
。
Firebase 即時資料庫可讓您輕鬆向多個內建供應商進行驗證,並為其產生驗證權杖。當使用者透過任一內建供應商完成驗證後,Auth 變數就會包含以下內容:
欄位 | 說明 |
---|---|
provider |
使用的驗證方式 (例如「password」、「anonymous」、「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'"
}
}
}
auth.token
包含 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 。字典的值是與帳戶相關聯的每個識別資訊提供者的專屬 ID 陣列。例如,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 |
與帳戶相關聯的 LoyaltyId (如有)。例如: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
索引鍵。
在規則結構中使用 $location
時,可以在規則運算式中使用相符的 $
變數,取得要讀取或寫入的實際子項名稱。因此,假設我們要授予每位使用者自己 /users/<user>
位置的讀取和寫入權限。我們可以使用:
{
"rules": {
"users": {
"$user": {
".read": "auth.uid === $user",
".write": "auth.uid === $user"
}
}
}
}
當用戶端嘗試存取 /users/barney
時,$user
預設位置會與 $user
等於「barney」相同。因此 .read
規則會檢查 auth.uid === 'barney'
。因此,只有在用戶端使用「barney」的 uid 進行驗證時,讀取
才會成功。/users/barney
現在
包含自 Unix 紀元以來的毫秒數 (根據 Firebase 即時資料庫伺服器)。
now
變數包含從 UNIX 紀元以來的毫秒數 (根據 Firebase 即時資料庫伺服器)。舉例來說,您可以利用這項程式碼,確認使用者的 created
時間一律不會設為未來時間:
{
"rules": {
"users": {
"$user": {
"created": {
".validate": "newData.val() < now"
}
}
}
}
}
root
與 Firebase 即時資料庫根目錄的目前資料相對應的 RuleDataSnapshot。
根變數可提供與 Firebase 即時資料庫根目錄的目前資料相對應的 RuleDataSnapshot。方便您在規則運算式中讀取資料庫中的任何資料。舉例來說,如果只想允許使用者在 /users/<id>/active
設為 True 時讀取 /comments
,可使用:
{
"rules": {
"comments": {
".read": "root.child('users').child(auth.uid).child('active').val() == true"
}
}
}
然後,如果 /users/barney/active
包含值 true,使用者就會使用「barney」做為 uid 進行驗證寫入「/comments
」節點
資料
與目前執行規則所在位置對應的 Firebase 即時資料庫資料相對應的 RuleDataSnapshot。
資料變數可提供與目前執行規則中資料庫位置 (而非根層級) 資料對應的 RuleDataSnapshot。
舉例來說,如果您想在 /users/<user>/public
設為 True 的情況下,允許任何用戶端存取 /users/<user>
,可以使用:
{
"rules": {
"users": {
"$user": {
".read": "data.child('public').val() == true"
}
}
}
}
資料變數可在 .read
、.write
和
.validate
規則。
新資料
如果允許寫入,則與查詢結果相對應的 RuleDataSnapshot。
如果是 .write
和 .validate
規則,新的資料變數會提供 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();
由於未寫入新資料,因此 .read
規則不提供 newData 變數。請只使用data。
RuleDataSnapshot:方法
val()
從這個 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(childPath)
如果指定的子已存在,則傳回 true。
引數:childPath
String
- 指向潛在子項位置的相對路徑。
傳回值:布林值 - true
如果指定子路徑有資料,其他 false
。
這個範例僅允許在含有子項「name」時寫入資料。
".validate": "newData.hasChild('name')"
hasChildren([孩童])
檢查子項是否存在。
引數:children
Array
選用 - 必須全部存在的子項鍵陣列。
傳回值:Boolean
- true
(如果 (指定) 有子項);其他 false
。
如果未提供引數,當 RuleDataSnapshot 有任何子項時,會傳回 true。如果提供子項名稱陣列,則只有在 RuleDataSnapshot 中包含所有指定的子項時,才會傳回 true。
這個範例僅允許在含有一或多個子項的資料寫入。
".validate": "newData.hasChildren()"
這個範例只允許寫入含有「name」的資料和「age」。
".validate": "newData.hasChildren(['name', 'age'])"
已存在()
如果這個 RuleDataSnapshot 包含任何資料,則傳回 true。
傳回值:Boolean
- true
(如果 RuleDataSnapshot 包含任何資料);其他為 false
。
如果這個 RuleDataSnapshot 包含任何資料,存在的函式會傳回 true。由於 data.exists()
等於 data.val() != null
,因此這只是便利函式。
本範例允許在沒有現有資料的情況下寫入。
".write": "!data.exists()"
getPriority()
取得 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
- true
如果資料是 String
;反之為 false
。
這個範例可確保寫入的新資料含有子項「name」子項取代為字串值。
".validate": "newData.child('name').isString()
isBoolean()
如果這個 RuleDataSnapshot 包含布林值,則傳回 true。
傳回值:Boolean
- true
如果資料是 Boolean
;其他 false
。
這個範例可確保寫入的新資料具有子項「active」替換成布林值
".validate": "newData.child('active').isBoolean()"
字串:屬性
長度
傳回字串長度。
傳回值:Number
- 字串中的字元數。
這個範例的字串長度至少要有 10 個半形字元。
".validate": "newData.isString() && newData.val().length >= 10"
字串:方法
contains(子字串)
如果字串包含指定子字串,則傳回 true。
引數:substring
String
- 要尋找的子字串。
傳回值:Boolean
- true
(如果字串包含指定的子字串);其他 false
。
這個範例要求資料必須是包含「@」的字串。
".validate": "newData.isString() && newData.val().contains('@')"
StartWith(子字串)
如果字串開頭為指定子字串,則傳回 true。
引數:substring
String
- 要用於開頭的子字串。
傳回值:Boolean
- true
(如果字串包含指定的子字串);其他 false
。
以下範例允許在 auth.token.identifier
開頭為「internal-」時允許讀取
".read": "auth.token.identifier.beginsWith('internal-')"
endWith(子字串)
如果字串結尾是指定子字串,則傳回 true。
引數:substring
String
- 要用於尋找結尾的子字串。
傳回值:Boolean
- true
(如果字串結尾是指定子字串);其他 false
。
這個範例允許讀取權限,如果 auth.token.identifier
結尾是「@company.com」
".read": "auth.token.identifier.endsWith('@company.com')"
replace(子字串, 取代)
傳回包含指定子字串所有例項,以指定取代字串取代的字串副本。
引數:substring String
- 要尋找的子字串。
replacement String
- 要取代子字串的字串。
傳回值:String
- 以取代子字串取代子字串後的新字串。
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
- 轉換為小寫的字串。
本範例允許讀取權限,因為 auth.token.identifier
全都存在於 /users
下。
".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"
toUpperCase()
傳回將字串轉換成大寫的字串。
傳回值:String
- 轉換為大寫的字串。
以下範例允許讀取,如果 auth.token.identifier
全都位於 /users
底下,就允許讀取。
".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"
match(規則運算式)
如果字串與指定的規則運算式常值相符,則會傳回 true。
傳回值:Boolean
- true
如果字串與規則運算式常值「regex」相符;其他 false
。
請參閱規則規則運算式說明文件。
運算子
+ (新增)
用於新增變數或字串串連。
以下範例可確保新值只會將現有值遞增 1。這有助於實作計數器:
".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"
- (否定或減去)
用於在規則運算式中否定值或減去兩個值。
這項驗證規則會檢查這個新值是位置的子項值相反值:
".validate": "newData.val() === -(data.child('quantity').val())"
以下範例使用減號,確保系統只會讀取過去 10 分鐘內的郵件:
".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,則會評估第二個運算元。如果條件為 False,則會評估第三個運算元。
下列驗證規則的新值可以是數字或布林值。如果這是數字,則必須大於 0。
".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"