Cloud Storage 的 Firebase 安全性規則參考資料

Cloud StorageFirebase Security Rules 可用於判斷誰具有讀取和寫入權限 儲存在 Cloud Storage 中的檔案以及檔案的結構 以及所含中繼資料Cloud Storage Security Rules 包含規則 請將 requestresource 視為允許或拒絕所需動作,例如 上傳檔案或擷取檔案中繼資料這些參考文件封面 規則類型、requestresource 的屬性、資料 Cloud Storage Security Rules使用的類型,以及錯誤發生方式。

規則

rule 是經過評估的運算式,可用於判斷 request 是否 就能執行所需動作

類型

允許

allow 規則包含方法,例如 readwrite 選用條件執行規則時,系統會評估條件。 如果條件評估為 true,就表示允許;否則 則系統會拒絕此方法沒有條件的 allow 規則一律允許 。

// Always allow method
allow <method>;

// Allow method if condition is true
allow <method>: if <condition>;

目前,allow 是唯一支援的規則類型。

要求方法

讀取

read 方法涵蓋所有讀取檔案資料或中繼資料的要求、 包括檔案下載和檔案中繼資料讀取

// Always allow reads
allow read;

// Allow reads if condition evaluates to true
allow read: if <condition>;

寫入

write 方法涵蓋所有寫入檔案資料或中繼資料的要求。 包括檔案上傳、檔案刪除和檔案中繼資料更新。

// Always allow writes
allow write;

// Allow writes if condition evaluates to true
allow write: if <condition>;

比對

系統會在使用者request (例如上傳或下載檔案) 時執行規則 比對符合規則的檔案路徑match 包含路徑和主體 其中必須包含至少一個 allow 規則如果沒有符合的路徑,要求 遭到拒絕。

您可以 match 完整命名的路徑,也可以插入萬用字元來比對所有 符合特定模式的路徑

路徑區隔

single_segment

您可以使用單一路徑區隔,建立與儲存檔案相符的規則 在「Cloud Storage」中。

// Allow read at "path" if condition evaluates to true
match /path {
  allow read: if <condition>;
}

您也可以使用多路徑區段和巢狀路徑:

// Allow read at "path/to/object" if condition evaluates to true
match /path {
  match /to {
    match /object {
      allow read: if <condition>;
    }
  }
}

{single_segment_wildcard}

如要將規則套用至相同路徑的多個檔案,您可以使用 來比對特定路徑中的所有檔案。萬用字元變數 是透過大括號括住變數 ({variable}),即可在路徑中宣告。 您可以在比對陳述式中以 string 的形式存取這個變數。

// Allow read at any path "/*", if condition evaluates to true
match /{single_path} {
  // Matches "path", "to", or "object" but not "path/to/object"
  allow read: if <condition>;
}

多個路徑片段和巢狀路徑也可使用萬用字元:

// Allow read at any path "/path/*/newPath/*", if condition evaluates to true
match /path/{first_wildcard} {
  match /newPath/{second_wildcard} {
    // Matches "path/to/newPath/newObject" or "path/from/newPath/oldObject"
    allow read: if <condition>;
  }
}

{multi_segment_wildcard=**}

如要比對路徑內或下方任意數量的路徑區隔,可以使用 多片段萬用字元,比對所有與 或 HTTP/HTTPS 位置這在提供使用者自己的任意形式時非常有用 儲存空間,或是建立符合許多不同路徑區段的規則 (例如 像是建立可公開讀取的檔案集 所有寫入作業)。

多片段萬用字元路徑的宣告方式與單一片段類似 萬用字元,並在變數結尾加上 =**{variable=**}。比對中有一個多片段萬用字元變數 視為 path 物件。

// Allow read at any path "/**", if condition evaluates to true
match /{multi_path=**} {
  // Matches anything at or below this, from "path", "path/to", "path/to/object", ...
  allow read: if <condition>;
}

要求

系統會在條件內提供 request 變數,以代表 發出要求request 變數有多種 屬性,可用來決定是否允許傳入的要求。

屬性

auth

當已通過驗證的使用者對 Cloud Storage 執行要求時, auth 變數會填入使用者的 uid (request.auth.uid),例如 以及 Firebase Authentication JWT (request.auth.token) 的聲明。

request.auth.token 包含下列部分或所有鍵:

欄位 說明
email 與帳戶相關聯的電子郵件地址 (如有)。
email_verified 如果使用者已確認他們能使用 email 地址,則請true。部分供應商會自動驗證他們擁有的電子郵件地址。
phone_number 與帳戶相關聯的電話號碼 (如果有的話)。
name 使用者的顯示名稱 (如有設定)。
sub 使用者的 Firebase UID。這個名稱在專案中是獨一無二的。
firebase.identities 與這位使用者帳戶相關聯的所有身分字典。字典金鑰可以是下列任一項目:emailphonegoogle.comfacebook.comgithub.comtwitter.com。字典的值是與帳戶相關聯的每個識別資訊提供者的專屬 ID 陣列。例如,auth.token.firebase.identities["google.com"][0] 包含與帳戶相關聯的第一個 Google 使用者 ID。
firebase.sign_in_provider 用於取得這個權杖的登入提供者。可以是下列任一字串:custompasswordphoneanonymousgoogle.comfacebook.comgithub.comtwitter.com
firebase.tenant 與帳戶相關聯的 LoyaltyId (如有)。例如:tenant2-m6tyz

如果使用自訂驗證,request.auth.token 也會包含任何自訂驗證 聲明。

當未經驗證的使用者執行要求時,request.authnull

// Allow requests from authenticated users
allow read, write: if request.auth != null;

path

path 變數包含 request 目前執行的路徑 下定決心

// Allow a request if the first path segment equals "images"
allow read, write: if request.path[0] == 'images';

resource

resource 變數包含所上傳檔案的中繼資料,或是 更新現有檔案的中繼資料這與 resource 變數,內含目前位於 而不是新的中繼資料

// Allow a request if the new value is smaller than 5MB
allow read, write: if request.resource.size < 5 * 1024 * 1024;

request.resource 包含 resource 的下列屬性:

屬性
name
bucket
metadata
size
contentType

time

time 變數包含代表目前伺服器時間的時間戳記 或要求評估某項要求的時間您可以使用這個金鑰來提供根據時間的存取權。 例如:僅允許在特定日期前上傳檔案 或只允許使用者在上傳檔案後的一小時內讀取檔案。

// Allow a read if the file was created less than one hour ago
allow read: if request.time < resource.timeCreated + duration.value(1, 'h');

提供許多函式以使用時間戳記時間長度

資源

resource 變數包含以下項目的檔案中繼資料: Cloud Storage,例如檔案名稱、大小、建立時間和 來建立自訂中繼資料

屬性

name

包含檔案全名的字串,包括檔案路徑。

// Allow reads if the resource name is "path/to/object"
allow read: if resource.name == 'path/to/object'

bucket

包含 Google Cloud Storage 的字串 以便儲存這個檔案

// Allow reads of all resources in your bucket
allow read: if resource.bucket == '<your-cloud-storage-bucket>'

generation

含有 Google Cloud Storage 的 int 產生物件 檔案。用於物件版本管理。

// Allow reads if the resource matches a known object version
allow read: if resource.generation == <known-generation>

metageneration

含有 Google Cloud Storage 的 int 物件中繼產生 檔案。用於物件版本管理。

// Allow reads if the resource matches a known object metadata version
allow read: if resource.metageneration == <known-generation>

size

包含檔案大小 (以位元組為單位) 的 int。

// Allow reads if the resource is less than 10 MB
allow read: if resource.size < 10 * 1024 * 1024;

timeCreated

代表檔案建立時間的時間戳記。

// Allow reads if the resource was created less than an hour ago
allow read: if resource.timeCreated < request.time + duration.value(60, "m")

updated

代表檔案上次更新時間的時間戳記。

// Allow reads if the resource was updated less than an hour ago
allow read: if resource.updated < request.time + duration.value(60, "m")

md5Hash

包含 MD5 雜湊 檔案。

// Allow writes if the hash of the uploaded file is the same as the existing file
allow write: if request.resource.md5Hash == resource.md5Hash;

crc32c

包含 crc32c 雜湊 檔案。

// Allow writes if the hash of the uploaded file is the same as the existing file
allow write: if request.resource.crc32c == resource.crc32c;

etag

包含 etag 檔案。

// Allow writes if the etag matches a known object etag
allow write: if resource.etag == <known-generation>

contentDisposition

包含檔案內容配置的字串。

// Allow reads if the content disposition matches a certain value
allow read: if resource.contentDisposition == 'inlined';

contentEncoding

包含檔案內容編碼的字串。

// Allow reads if the content is encoded with gzip
allow read: if resource.contentEncoding == 'gzip';

contentLanguage

包含檔案內容語言的字串。

// Allow reads if the content language is Japanese
allow read: if resource.contentLanguage == 'ja';

contentType

包含檔案內容類型的字串。

// Allow reads if the content type is PNG.
allow read: if resource.contentType == 'image/png';

metadata

Map<String, String>,包含開發人員提供的額外中繼資料 只要使用來自這些領域的 小型資料集訓練即可

// Allow reads if a certain metadata field matches a desired value
allow read: if resource.metadata.customProperty == 'customValue';

Firestore.get 和 Firestore.exists

firestore.get()firestore.exists() 函式可讓您存取 「Cloud Firestore」中的文件來評估複雜的授權條件。

firestore.get()firestore.exists() 函式都應符合要求 完全指定文件路徑使用變數建構 firestore.get()firestore.exists(),您需要明確逸出 使用 $(variable) 語法的變數。

Firestore.get

取得 Cloud Firestore 文件的內容。

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.uid)).data.memberships
    }
  }
}

Firestore.exists

檢查 Cloud Firestore 文件是否存在。

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.uid))
    }
  }
}

服務

serviceCloud Storage Security Rules 檔案的第一個宣告,而 會指定要套用這些規則的服務。

名稱

name

要套用的服務規則名稱。目前唯一值: firebase.storage

// Specify the service name
service firebase.storage {
  match /b/{bucket}/o {
    ...
  }
}

資料類型

Rules 語言可讓您使用 is 運算子檢查類型。

// For example
a is null
a is string

null

null 資料類型代表不存在的值。

allow read: if request.auth != null;

bool

bool 類型代表布林值 truefalse

allow read: if true;   // always succeeds
allow write: if false; // always fails

比較

您可以使用 == 運算子 != 比較布林值。

布林運算

作業 運算式
AND x && y
OR x || y
NOT !x

作業短路,且可傳回 truefalseError (錯誤),

allow read: if true || false;   // always succeeds, short circuits at true
allow write: if false && true; // always fails, short circuits at false

intfloat

intfloat 類型代表數字。整數為:01-2 等。 ,而浮點值是:1.0-2.03.33 等。

Ints 為帶正負號的 64 位元值,而浮點值符合 64 位元 IEEE 754 標準值。 在比較和使用時,「int」類型的值將會強制轉換為 float 帶有 float 值的算術運算。

比較

您可以使用 ==!=><>=<= 運算子。

算術

整數和浮點數的加減法如下: 否定:

作業 運算式
x + y
x - y
x * y
x / y
模數 x % y
否定 -x

數學函式

Cloud StorageFirebase Security Rules 也提供許多數學輔助工具 可簡化運算式的函式:

函式 說明
math.ceil(x) 數值天花板
math.floor(x) 數值樓層
math.round(x) 將輸入值四捨五入至最接近的整數
math.abs(x) 輸入內容的絕對值
math.isInfinite(x) 測試該值是否為 ±∞,傳回 bool
math.isNaN(x) 測試該值是否不是數字 NaN,而是傳回 bool

string

比較

使用 ==!=><>=<= 運算子。

串連

字串可以使用 + 運算子串連。

// Concatenate a file name and extension
'file' + '.txt'

索引和範圍

index 運算子 string[] 會傳回包含字元的字串 顯示在字串中提供的索引。

// Allow reads of files that begin with 'a'
match /{fileName} {
  allow read: if fileName[0] == 'a';
}

range 運算子 string[i:j] 會傳回包含 指定索引之間的字元,從 i (含) 到 j (不含)。如未指定 ij,則預設值為 0,而且大小 字串,但至少必須指定 ij 才有效

// Allow reads of files that begin with 'abcdef'
match /{fileName} {
  allow read: if fileName[0:6] == 'abcdef';
}

如果提供索引,indexrange 運算子會產生錯誤 超出字串邊界

size

傳回字串中的字元數。

// Allow files with names less than 10 characters
match /{fileName} {
  allow write: if fileName.size() < 10;
}

matches

執行規則運算式比對,如果字串與true 特定規則運算式用途 Google RE2 語法

// Allow writes to files which end in ".txt"
match /{fileName} {
  allow write: if fileName.matches('.*\\.txt')
}

split

根據提供的規則運算式分割字串並傳回 list 字串。請使用 Google RE2 語法

// Allow files named "file.*" to be uploaded
match /{fileName} {
  allow write: if fileName.split('.*\\..*')[0] == 'file'
}

path

路徑是類似目錄的名稱,可選擇採用模式比對。 出現正斜線 /,表示路徑區段的起點。

path

string 引數轉換為 path

// Allow reads on a specific file path
match /{allFiles=**} {
  allow read: if allFiles == path('/path/to/file');
}

timestamp

時間戳記以世界標準時間為準,可能的值從 0001-01-01T00.00.00Z 開始 結尾是 9999-12-31T23.59.59Z。

比較

您可以使用 ==!=><>=<= 運算子。

算術

時間戳記支援在時間戳記與時間長度之間進行加減,做為 如下:

運算式 結果
timestamp + duration timestamp
duration + timestamp timestamp
timestamp - duration timestamp
timestamp - timestamp duration
duration + duration duration
duration - duration duration

date

僅包含 yearmonthdaytimestamp 值。

// Allow reads on the same day that the resource was created.
allow read: if request.time.date() == resource.timeCreated.date()

year

以 int 表示的年份值,從 1 到 9999。

// Allow reads on all requests made before 2017
allow read: if request.time.year() < 2017

month

以 int 表示的月份值 (從 1 到 12)。

// Allow reads on all requests made during the month of January
allow read: if request.time.month() == 1;

day

以入侵表示當月的當天 (1 到 31)。

// Allow reads on all requests made during the first day of each month
allow read: if request.time.day() == 1;

time

包含目前時間的 duration 值。

// Allow reads on all requests made before 12PM
allow read: if request.time.time() < duration.time(12, 0, 0, 0);

hours

小時值,以 int 表示 (0 到 23)。

// Allow reads on all requests made before 12PM
allow read: if request.time.hours() < 12;

minutes

以 int 表示的分鐘值,從 0 到 59。

// Allow reads during even minutes of every hour
allow read: if request.time.minutes() % 2 == 0;

seconds

以 int 表示的秒數值,從 0 到 59。

// Allow reads during the second half of each minute
allow read: if request.time.seconds() > 29;

nanos

以 int 表示的分數秒數。

// Allow reads during the first 0.1 seconds of each second
allow read: if request.time.nanos() < 100000000;

dayOfWeek

星期幾,從 1 (週一) 到 7 (週日)。

// Allow reads on weekdays (Monday to Friday)
allow read: if request.time.dayOfWeek() < 6;

dayOfYear

目前一年中的日期,這個值可介於 1 到 366 之間。

// Allow reads every fourth day
allow read: if request.time.dayOfYear() % 4 == 0;

toMillis

傳回目前從 Unix 紀元開始計算的毫秒數。

// Allow reads if the request is made before a specified time
allow read: if request.time.toMillis() < <milliseconds>;

duration

持續時間值以秒加上小數秒數表示 奈秒

比較

您可以使用 ==!=><>=<= 運算子。

算術

時間長度支援將時間戳記與時間長度相加,可當做 如下:

運算式 結果
timestamp + duration timestamp
duration + timestamp timestamp
timestamp - duration timestamp
timestamp - timestamp duration
duration + duration duration
duration - duration duration

seconds

目前時間長度的秒數。必須介於 -315,576,000,000 之間 以及 +315,576,000,000 (含) 在內

nanos

目前時間長度的小數秒數 (以奈秒表示)。必選 -999,999,999 和 +999,999,999 (含) 之間。對於 0 以外的 0 秒以及 非零奈秒的機率,兩者的跡象必須一致。

duration.value

您可以使用 duration.value(int magnitude, string units) 建立時間長度 函式,根據指定的規模和單位建立時間長度。

// All of these durations represent one hour:
duration.value(1, "h")
duration.value(60, "m")
duration.value(3600, "s")

可能的unit如下:

時間長度 unit
w
d
小時 h
分鐘 m
s
毫秒 ms
奈秒 ns

duration.time

您可以使用 duration.time(int hours, int minutes, int seconds, int nanoseconds) 函式, 這會建立指定小時、分鐘、秒數和 奈秒

// Create a four hour, three minute, two second, one nanosecond duration
duration.time(4, 3, 2, 1)

list

清單包含值的有序陣列,類型可以是:nullboolintfloatstringpathlistmaptimestampduration

假設 xy 類型為 listi,且類型為 int 類型j

建立時間

如要建立清單,請在方括號之間加入值:

// Create a list of strings
['apples', 'grapes', 'bananas', 'cheese', 'goats']

比較

您可以使用 == 運算子 != 比較清單。兩份清單的品質 所有值都必須相同

索引和範圍

index 運算子 list[] 會傳回位於 請參考閱讀清單,進一步瞭解 如何選擇 Kubeflow Pipelines SDK 或 TFX

// Allow reads of all files that begin with 'a'
match /{fileName} {
  allow read: if fileName[0] == 'a';
}

range 運算子 list[i:j] 會傳回清單之間 指定的索引,從 i (含) 到 j (不含)。如果 ij 為 未指定,則預設為 0 和清單大小,但 至少須指定 ij,範圍才有效。

// Allow reads of all files that begin with 'abcdef'
match /{fileName} {
  allow read: if fileName[0:6] == 'abcdef';
}

in

如果想要的值出現在清單中,則傳回 true;如果沒有指定值,則傳回 false

// Allow read if a filename has the string 'txt' in it
match /{fileName} {
  allow read: if 'txt' in fileName.split('\\.');
}

join

將字串清單合併成單一字串,並以指定字串分隔。

// Allow reads if the joined array is 'file.txt'
allow read: if ['file', 'txt'].join('.') == 'file.txt';

size

清單中的項目數量。

// Allow read if there are three items in our list
allow read: if ['foo', 'bar', 'baz'].size() == 3;

hasAll

如果所有值都出現在清單中,則傳回 true

// Allow read if one list has all items in the other list
allow read: if ['file', 'txt'].hasAll(['file', 'txt']);

map

對應包含鍵/值組合,其中的鍵為字串,值可以是任意值 /:nullboolintfloatstringpathlistmaptimestampduration

建立時間

如要建立對應,請在括號之間加入鍵/值組合:

// Create a map of strings to strings
{
  'mercury': 'mars',
  'rain': 'cloud',
  'cats': 'dogs',
}

比較

您可以使用 == 運算子 != 比較地圖。兩張地圖的相等 會要求對應中所有鍵,且所有值都相同。

索引

系統會使用括號或點標記法存取對應中的值:

// Access custom metadata properties
allow read: if resource.metadata.property == 'property'
allow write: if resource.metadata['otherProperty'] == 'otherProperty'

如果沒有任何索引鍵,系統會傳回 error

in

如果所需的金鑰出現在地圖中,則傳回 true;如果沒有所需的金鑰,則傳回 false

// Allow reads if a property is present in the custom metadata
allow read: if property in resource.metadata;

size

地圖中的索引鍵數量。

// Allow reads if there's exactly one custom metadata key
allow read: if resource.metadata.size() == 1;

keys

對應中所有索引鍵的清單。

// Allow reads if the first metadata key is 'myKey'
allow read: if resource.metadata.keys()[0] == 'myKey';

values

按鍵順序列出對應中的所有值。

// Allow reads if the first metadata value is 'myValue'
allow read: if resource.metadata.values()[0] == 'myValue';

錯誤

錯誤評估

發生錯誤時,Cloud StorageFirebase Security Rules 會繼續評估。 這項功能很實用,因為條件式 &&|| 運算式可能會吸收錯誤 如果條件式會短路為 falsetrue 。例如:

運算式 結果
error && true error
error && false false
error || true true
error || false error

發生錯誤的常見原因包括:除以零、存取值 清單或地圖,並傳遞不正確類型的值 至函式

// Error if resource.size is zero
allow read: if 1000000 / resource.size;

// Error, key doesn't exist
allow read: if resource.metadata.nonExistentKey == 'value';

// Error, no unit 'y' exists
allow read: if request.time < resource.timeCreated + duration.value(1, 'y');