本頁面簡介已簽署的網址,並說明如何搭配 Cloud CDN 使用。使用已簽署的網址,可將限時的資源存取權提供給任何知道該網址的使用者,且不限於 Google 帳戶擁有者。
已簽署的網址可用來提供有限權限,允許使用者在時限內提出要求。這類網址的查詢字串中包含驗證資訊,可讓不具憑證的使用者對資源執行特定動作。產生已簽署的網址時,您指定的使用者或服務帳戶須具備充分的權限,有權提出與該網址相關的要求。
產生已簽署網址後,任何知道該網址的使用者,都可以用來在指定的一段時間內執行特定動作,例如讀取物件。
已簽署的網址也支援選用的 URLPrefix 參數,可根據通用前置字元提供多個網址的存取權。
如要將存取範圍限制在特定網址前置字元,可考慮使用已簽署的 Cookie。
事前準備
使用已簽署的網址前,請先完成下列步驟:
確認已啟用 Cloud CDN;如需操作說明,請參閱「使用 Cloud CDN」。啟用 Cloud CDN 之前,您可以先在後端設定已簽署的網址,但這類網址須等到 Cloud CDN 啟用後才會生效。
請視需要更新至最新版 Google Cloud CLI:
gcloud components update
請參閱「已簽署的網址和 Cookie」瞭解概況。
設定已簽署的要求金鑰
如要為已簽署的網址或 Cookie 建立金鑰,請完成以下各節說明的步驟。
安全性考量
在下列情況中,Cloud CDN「不會」驗證要求:
- 要求未經簽署。
- 要求所用的後端服務或後端 bucket 未啟用 Cloud CDN。
已簽署的要求「一律」須先在來源端經過驗證,才能提供回應。這是因為來源可用於提供混合已簽署和未簽署的內容,且用戶端可直接存取來源。
- Cloud CDN 不會封鎖沒有
Signature查詢參數或Cloud-CDN-CookieHTTP Cookie 的要求,且會拒絕要求參數無效 (或格式有誤) 的要求。 - 應用程式偵測到無效簽章時,需確保應用程式會以
HTTP 403 (Unauthorized)回應代碼回應。HTTP 403回應代碼不可快取。 - 系統會分別快取已簽署和未簽署要求的回應,因此對有效已簽署要求的成功回應,絕不會用來處理未簽署的要求。
- 如果應用程式將可快取的回應代碼傳送給無效的要求,往後的有效要求可能會遭到拒絕。
如果使用 Cloud Storage 後端,請務必移除公開存取權,Cloud Storage 才能拒絕缺少有效簽章的要求。
下表彙整了相關行為。
| 要求具有簽章 | 快取命中 | 行為 |
|---|---|---|
| 否 | 否 | 轉送至後端來源。 |
| 否 | 是 | 從快取提供。 |
| 是 | 否 | 驗證簽章。簽章有效則轉送至後端來源。 |
| 是 | 是 | 驗證簽章。簽章有效則從快取提供。 |
建立已簽署的要求金鑰
如要啟用 Cloud CDN 已簽署的網址和 Cookie 支援功能,請在已啟用 Cloud CDN 的後端服務和/或後端 bucket 中,建立一或多組金鑰。
在每個後端服務或後端 bucket 中,依據安全需求建立和刪除金鑰。每個後端一次最多可以設定三組金鑰。建議您定期刪除最舊的金鑰並新增金鑰,然後在簽署網址或 Cookie 時使用新金鑰,藉此輪換金鑰。
各組金鑰彼此不相依,因此可在多個後端服務和後端 bucket 中使用相同的金鑰名稱。金鑰名稱長度上限 63 個字元,如要為金鑰命名,請使用 A-Z、a-z、0-9、_ (底線) 和 - (連字號) 字元。
建立金鑰時,請務必確保金鑰安全,因為任何使用者只要取得其中一組金鑰,就能建立 Cloud CDN 接受的已簽署網址或 Cookie,直到該組金鑰從 Cloud CDN 中刪除為止。金鑰會儲存在您用來產生已簽署網址或 Cookie 的電腦中。另外,Cloud CDN 也會儲存金鑰並用於驗證要求簽章。
為確保金鑰隱密性,請勿在傳送至任何 API 要求的回應中加入金鑰值。如果金鑰遺失,您必須建立新的金鑰。
如要建立已簽署的要求金鑰,請按照下列步驟操作。
控制台
- 前往 Google Cloud 控制台的「Cloud CDN」頁面。
- 按一下要新增金鑰的來源名稱。
- 在「Origin details」(來源詳細資料) 頁面上,按一下「Edit」(編輯) 按鈕。
- 在「Origin basics」(來源基本資訊) 部分,點選「Next」(下一步),開啟「Host and path rules」(主機與路徑規則) 部分。
- 在「Host and path rules」(主機與路徑規則) 部分,點選「Next」(下一步),開啟「Cache performance」(快取效能) 部分。
- 在「Restricted content」(受限制的內容) 部分,選取「Restrict access using signed URLs and signed cookies」(透過已簽署的網址和 Cookie 限制存取權限)。
按一下「Add signing key」(新增簽署金鑰)。
- 為新的簽署金鑰指定不重複的名稱。
將「Key creation method」(金鑰建立方法) 設為「Automatically generate」(自動產生),或是按一下「Let me enter」(讓我輸入),然後指定簽署金鑰值。
如果採用前者,請將自動產生的簽署金鑰值複製到私密檔案,方便用於建立已簽署的網址。
按一下「Done」(完成)。
在「Cache entry maximum age」(快取項目存在時間長度上限) 部分輸入值,然後選取時間單位。
按一下「Done」(完成)。
gcloud
gcloud 指令列工具會從您指定的本機檔案讀取金鑰。金鑰檔必須以下列方式建立:產生高度隨機 128 個位元,使用 base64 進行編碼,然後將字元 + 替換為 -,並將字元 / 替換為 _。詳情請參閱 RFC 5116。產生高度隨機金鑰是重要步驟。在 UNIX 等系統上,您可以使用下列指令,產生高度隨機金鑰並儲存在金鑰檔案中:
head -c 16 /dev/urandom | base64 | tr +/ -_ > KEY_FILE_NAME
如要將金鑰新增至後端服務,請按照下列步驟操作:
gcloud compute backend-services \ add-signed-url-key BACKEND_NAME \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME
如要將金鑰新增至後端 bucket,請按照下列步驟操作:
gcloud compute backend-buckets \ add-signed-url-key BACKEND_NAME \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME
設定 Cloud Storage 權限
如果您使用 Google Cloud Storage,且已限制哪些使用者可以讀取物件,則必須將 Cloud CDN 服務帳戶新增至 Cloud Storage 的 ACL,藉此授予 Cloud CDN 讀取物件的權限。
您不需要建立服務帳戶,首次將金鑰新增至專案後端 bucket 時,系統會自動建立服務帳戶。
執行下列指令前,請先將至少一個金鑰新增至專案中的後端 bucket。若沒有執行這個步驟,指令就會失敗並發生錯誤,因為必須先為專案新增一或多個金鑰,系統才會建立 Cloud CDN 快取填補服務帳戶。
gcloud storage buckets add-iam-policy-binding gs://BUCKET \ --member=serviceAccount:service-PROJECT_NUMBER@cloud-cdn-fill.iam.gserviceaccount.com \ --role=roles/storage.objectViewer
將 PROJECT_NUMBER 替換為專案編號,並將 BUCKET 替換為儲存空間 bucket。
Cloud CDN 服務帳戶 service-PROJECT_NUMBER@cloud-cdn-fill.iam.gserviceaccount.com 不會顯示在專案的服務帳戶清單中。這是因為 Cloud CDN 服務帳戶的擁有者為 Cloud CDN,而非專案。
如要進一步瞭解專案編號,請參閱 Google Cloud 控制台說明文件中的「尋找專案 ID 與專案編號」。
自訂快取時間上限
無論後端的 Cache-Control 標頭為何,Cloud CDN 都會快取已簽署要求的回應。在不重新驗證的情況下快取回應的時間長度上限,是透過 signed-url-cache-max-age 標記設定,預設上限為一小時,不過可以按照下列步驟修改。
如要設定後端服務或後端 bucket 的快取時間長度上限,請執行下列任一指令:
gcloud compute backend-services update BACKEND_NAME \ --signed-url-cache-max-age MAX_AGE
gcloud compute backend-buckets update BACKEND_NAME \ --signed-url-cache-max-age MAX_AGE
列出已簽署的要求金鑰名稱
如要列出後端服務或後端 bucket 的金鑰,請執行下列任一指令:
gcloud compute backend-services describe BACKEND_NAME
gcloud compute backend-buckets describe BACKEND_NAME
刪除已簽署的要求金鑰
透過特定金鑰簽署的網址失效之後,請執行下列其中一個指令,從後端服務或後端 bucket 中刪除該組金鑰:
gcloud compute backend-services \ delete-signed-url-key BACKEND_NAME --key-name KEY_NAME
gcloud compute backend-buckets \ delete-signed-url-key BACKEND_NAME --key-name KEY_NAME
簽署網址
最後一個步驟是簽署並發布網址。您可以使用 gcloud compute sign-url 指令或自行編寫的程式碼簽署網址。如需大量已簽署的網址,使用自訂程式碼的效果較好。
建立已簽署的網址
請按照下列操作說明,使用 gcloud compute sign-url 指令建立已簽署的網址。此步驟假設您已建立金鑰。
控制台
您無法使用 Google Cloud 控制台建立已簽署的網址,但可以使用 Google Cloud CLI,或透過下列範例撰寫自訂程式碼。
gcloud
Google Cloud CLI 包含可用來簽署網址的指令。請參閱自行編寫程式碼的相關段落,瞭解用於實作演算法的指令。
gcloud compute sign-url \ "URL" \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME \ --expires-in TIME_UNTIL_EXPIRATION \ [--validate]
這項指令會從 KEY_FILE_NAME 讀取並解碼 base64url 編碼的金鑰值,然後輸出已簽署的網址,供您用於對指定的網址執行 GET 或 HEAD 要求。
例如:
gcloud compute sign-url \ "https://example.com/media/video.mp4" \ --key-name my-test-key \ --expires-in 30m \ --key-file sign-url-key-file
URL 必須是含有路徑元件的有效網址。舉例來說,http://example.com 無效,但 https://example.com/ 和 https://example.com/whatever 都是有效的網址。
如果提供選用的 --validate 旗標,這項指令會使用產生的網址傳送 HEAD 要求,並顯示 HTTP 回應代碼。如果已簽署的網址正確,回應代碼會與後端傳送的結果代碼相同。如果回應代碼不相同,請重新檢查 KEY_NAME 與指定檔案的內容,確認 TIME_UNTIL_EXPIRATION 的值至少為幾秒鐘。
如果沒有提供 --validate 旗標,系統就不會驗證下列項目:
- 輸入內容
- 產生的網址
- 產生的已簽署網址
以程式輔助方式建立已簽署的網址
下列程式碼範例示範如何以程式輔助方式建立已簽署的網址。
Go
Ruby
.NET
Java
Python
PHP
以程式輔助方式建立含有網址前置字元的已簽署網址
以下程式碼範例示範如何以程式輔助方式,建立含有網址前置字元的已簽署網址。
Go
Java
Python
產生自訂的已簽署網址
自行編寫程式碼來產生已簽署的網址時,目標是建立採用以下格式或演算法的網址;所有網址參數都區分大小寫,且須按照以下順序排列:
https://example.com/foo?Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
如要產生已簽署的網址,請按照下列步驟操作:
確保要簽署的網址不含
Signature查詢參數。決定網址的到期時間,並附加
Expires查詢參數,此參數的值須為以世界標準時間為準的到期時間,也就是從 1970-01-01 00:00:00 UTC 起算的秒數。為盡可能提升安全性,請根據您的用途,將這個值設為可能的最短時間範圍。已簽署網址的有效期限越長,取得網址的使用者意外或刻意將這個網址分享給其他人的風險就越高。設定金鑰名稱。必須根據提供網址的後端服務或後端 bucket,使用相應金鑰來簽署該網址。建議採用金鑰輪替方式,使用最近新增的金鑰。附加
&KeyName=KEY_NAME即可將金鑰新增至網址。請將KEY_NAME替換為在「建立已簽署的要求金鑰」中建立的金鑰名稱。簽署網址。請按照下列步驟建立已簽署的網址,並確認查詢參數與步驟 1 正上方顯示的順序完全一致,而且已簽署的網址沒有任何變動。
a. 使用與您稍早所選金鑰名稱相對應的 Secret,透過 HMAC-SHA1 雜湊處理整個網址 (包含開頭的
http://或https://以及結尾的&KeyName...)。請使用原始 16 位元組 Secret 金鑰,而非 base64url 編碼的金鑰。如有需要,請將金鑰解碼。b. 使用 base64url 編碼將結果編碼。
c. 將
&Signature=附加至網址,後面接著已編碼的簽章。請勿將簽章結尾的=字元轉換為百分比編碼形式%3D。
使用已簽署網址的網址前置字元
您無須使用 Expires 和 KeyName 查詢參數來簽署整個要求網址,可以只簽署 URLPrefix、Expires 和 KeyName 查詢參數。這樣一來,即可在多個符合 URLPrefix 的網址中重複使用同一組 URLPrefix、Expires、KeyName 和 Signature 查詢參數,無需為不同網址分別建立新簽章。
在下列範例中,醒目顯示的文字是您簽署的參數。照常將 Signature 附加為最終查詢參數。
https://media.example.com/videos/id/master.m3u8?userID=abc123&starting_profile=1&URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv&Expires=1566268009&KeyName=mySigningKey&Signature=8NBSdQGzvDftrOIa3WHpp646Iis=
與簽署完整要求網址不同,使用 URLPrefix 簽署時,並不會簽署任何查詢參數,因此可在網址中任意加入查詢參數。另一個與完整要求網址簽章不同之處是,這些額外的查詢參數,可以出現在組成簽章的查詢參數前後。因此,以下含有已簽署網址前置字元的網址,也是有效網址:
https://media.example.com/videos/id/master.m3u8?userID=abc123&URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv&Expires=1566268009&KeyName=mySigningKey&Signature=8NBSdQGzvDftrOIa3WHpp646Iis=&starting_profile=1
URLPrefix 代表安全網址 base64 編碼的網址前置字元,涵蓋適用該簽章的所有路徑。
URLPrefix 會將網址配置 (http:// 或 https://)、FQDN 和選用路徑編碼。在路徑結尾加上 / 雖非必要,但建議加上。前置字元不得包含查詢參數或片段,例如 ? 或 #。
舉例來說,下列兩項要求都符合 https://media.example.com/videos:
https://media.example.com/videos?video_id=138183&user_id=138138https://media.example.com/videos/137138595?quality=low
前置字元的路徑是當成文字子字串使用,而非嚴格的目錄路徑。舉例來說,前置字元 https://example.com/data 會同時授予下列兩個項目的存取權:
/data/file1/database
為避免發生這類錯誤,前置字元建議一律以 / 結尾,除非您刻意選擇以部分檔案名稱結尾 (例如 https://media.example.com/videos/123),以便授予下列項目的存取權:
/videos/123_chunk1/videos/123_chunk2/videos/123_chunkN
如果要求的網址與 URLPrefix 不符,Cloud CDN 會拒絕要求,並向用戶端傳回 HTTP 403 錯誤。
驗證已簽署的網址
驗證已簽署網址的程序,基本上與產生已簽署的網址相同。舉例來說,假設您想驗證下列已簽署的網址:
https://example.com/PATH?Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
可以使用透過 KEY_NAME 命名的 Secret 金鑰,獨立產生下列網址的簽章:
https://example.com/PATH?Expires=EXPIRATION&KeyName=KEY_NAME
然後確認是否與 SIGNATURE 相符。
假設您要驗證具有 URLPrefix 的已簽署網址,如下所示:
https://example.com/PATH?URLPrefix=URL_PREFIX&Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
首先,請確認 URL_PREFIX 的 base64 解碼值是否為 https://example.com/PATH 的前置字元。如果是,就可以計算下列項目的簽章:
URLPrefix=URL_PREFIX&Expires=EXPIRATION&KeyName=KEY_NAME
然後確認是否與 SIGNATURE 相符。
以網址為準的簽署方法,指的是簽章為查詢參數的一部分,或是以網址路徑元件形式嵌入。在這種情況中,系統會先從網址中移除簽章和相關參數,再將要求傳送至來源。這樣一來,來源處理要求時,簽章就不會引發轉送問題。如要驗證這類要求,可以檢查 x-client-request-url 要求標頭,此標頭中包含移除已簽署元件前的原始 (已簽署) 用戶端要求網址。
移除 Cloud Storage bucket 的公開存取權
為確保已簽署的網址妥善保護內容,原始伺服器不得授予該內容的公開存取權。使用 Cloud Storage bucket 時,常見的做法是將物件設為暫時公開存取,以便進行測試。啟用已簽署的網址後,請務必移除 bucket 中 allUsers (及 allAuthenticatedUsers,如果有的話) 的 READ 權限,也就是 Storage 物件檢視者 Identity and Access Management 角色。
停用 bucket 的公開存取權後,個別使用者若具備存取權限 (例如 OWNER 權限),不需要已簽署的網址就能繼續存取 Cloud Storage。
如要移除 Cloud Storage bucket 的公開 allUsers READ 存取權,請反向操作「將 bucket 中的所有物件設為可公開讀取」所述的步驟。
發布及使用已簽署的網址
您可依據需求發布從 Google Cloud CLI 傳回的網址,或是透過自訂程式碼產生的網址。建議您僅簽署 HTTPS 網址,因為 HTTPS 提供的安全傳輸方式,可避免已簽署網址的 Signature 元件遭攔截。同樣地,請務必透過安全傳輸通訊協定 (例如 TLS/HTTPS) 發布已簽署的網址。