Cloud Storage 的 Firebase Security Rules 可用於判斷誰具有讀取和寫入權限
儲存在 Cloud Storage 中的檔案以及檔案的結構
以及所含中繼資料Cloud Storage Security Rules 包含規則
請將 request
和 resource
視為允許或拒絕所需動作,例如
上傳檔案或擷取檔案中繼資料這些參考文件封面
規則類型、request
和 resource
的屬性、資料
Cloud Storage Security Rules使用的類型,以及錯誤發生方式。
規則
rule
是經過評估的運算式,可用於判斷 request
是否
就能執行所需動作
類型
允許
allow
規則包含方法,例如 read
或 write
選用條件執行規則時,系統會評估條件。
如果條件評估為 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 |
與這位使用者帳戶相關聯的所有身分字典。字典金鑰可以是下列任一項目: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 |
如果使用自訂驗證,request.auth.token
也會包含任何自訂驗證
聲明。
當未經驗證的使用者執行要求時,request.auth
為 null
。
// 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)) } } }
服務
service
是 Cloud 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
類型代表布林值 true
或 false
。
allow read: if true; // always succeeds allow write: if false; // always fails
比較
您可以使用 ==
運算子 !=
比較布林值。
布林運算
作業 | 運算式 |
---|---|
AND |
x && y |
OR |
x || y |
NOT |
!x |
作業短路,且可傳回 true
、false
或
Error (錯誤),
allow read: if true || false; // always succeeds, short circuits at true allow write: if false && true; // always fails, short circuits at false
int
和float
int
和 float
類型代表數字。整數為:0
、1
、-2
等。
,而浮點值是:1.0
、-2.0
、3.33
等。
Ints 為帶正負號的 64 位元值,而浮點值符合 64 位元 IEEE 754 標準值。
在比較和使用時,「int
」類型的值將會強制轉換為 float
帶有 float
值的算術運算。
比較
您可以使用 ==
、!=
、>
、<
、
>=
和 <=
運算子。
算術
整數和浮點數的加減法如下: 否定:
作業 | 運算式 |
---|---|
加 | x + y |
減 | x - y |
乘 | x * y |
除 | x / y |
模數 | x % y |
否定 | -x |
數學函式
Cloud Storage 的 Firebase 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
(不含)。如未指定 i
或 j
,則預設值為 0,而且大小
字串,但至少必須指定 i
或 j
才有效
// Allow reads of files that begin with 'abcdef' match /{fileName} { allow read: if fileName[0:6] == 'abcdef'; }
如果提供索引,index
和 range
運算子會產生錯誤
超出字串邊界
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
僅包含 year
、month
和 day
的 timestamp
值。
// 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
清單包含值的有序陣列,類型可以是:null
、bool
、
int
、float
、string
、path
、list
、map
、timestamp
或 duration
。
假設 x
和 y
類型為 list
和 i
,且類型為 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
(不含)。如果 i
或 j
為
未指定,則預設為 0 和清單大小,但
至少須指定 i
或 j
,範圍才有效。
// 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
對應包含鍵/值組合,其中的鍵為字串,值可以是任意值
/:null
、bool
、int
、float
、string
、path
、list
、map
、
timestamp
或 duration
。
建立時間
如要建立對應,請在括號之間加入鍵/值組合:
// 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 Storage 的 Firebase Security Rules 會繼續評估。
這項功能很實用,因為條件式 &&
和 ||
運算式可能會吸收錯誤
如果條件式會短路為 false
或 true
。例如:
運算式 | 結果 |
---|---|
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');