本頁面簡介已簽署的 Cookie,並說明如何搭配 Cloud CDN 使用。使用已簽署的 Cookie,可將一組檔案的限時資源存取權提供給使用者,且不限於 Google 帳戶擁有者。
已簽署的 Cookie 是已簽署網址的替代方案。當應用程式無法為每位使用者分別簽署數大量網址,已簽署的 Cookie 可保護存取權限。
已簽署的 Cookie 可發揮以下作用:
- 提供限時權杖,授權使用者存取受保護的內容 (不必為每個網址簽署)。
- 將使用者的存取範圍限制於特定網址前置字元 (例如
https://media.example.com/videos/),僅允許授權使用者存取該範圍內的受保護內容。 - 讓網址和媒體資訊清單維持不變,簡化封裝管道並提升可快取性。
如要將存取權範圍限制在特定網址,建議使用已簽署的網址。
事前準備
使用已簽署的 Cookie 前,請先完成下列步驟:
確認已啟用 Cloud CDN;如需操作說明,請參閱「使用 Cloud CDN」。啟用 Cloud CDN 前,您可以先在後端設定已簽署的 Cookie,但這類網址須等到 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 4648。產生高度隨機金鑰是重要步驟。在 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
建立政策
已簽署的 Cookie 政策是一連串的 key-value 配對 (以 : 字元分隔),類似已簽署網址中使用的查詢參數。請參閱「向使用者簽發 Cookie」中的範例。
政策代表有效要求須具備的參數。系統會使用雜湊式訊息驗證碼 (HMAC) 簽署政策,而 Cloud CDN 會對每個要求驗證該簽章。
定義政策格式和欄位
您須按照下列順序定義四個必填欄位:
URLPrefixExpiresKeyNameSignature
已簽署 Cookie 政策中的 key-value 配對會區分大小寫。
URLPrefix
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 錯誤。
Expires
Expires 須為 Unix 時間戳記 (自 1970 年 1 月 1 日算起的秒數)。
KeyName
KeyName 是專為後端 bucket 或後端服務建立的金鑰名稱,區分大小寫。
Signature
Signature 是安全網址 base64 編碼的 HMAC-SHA-1 簽章,由構成 Cookie 政策的欄位組成。系統會對每項要求驗證此簽章,如果簽章無效,便會拒絕要求並傳回 HTTP 403 錯誤。
以程式輔助方式建立已簽署的 Cookie
下列程式碼範例示範如何以程式輔助方式,建立已簽署的 Cookie。
Go
Java
Python
驗證已簽署的 Cookie
驗證已簽署 Cookie 的程序,基本上與產生已簽署的 Cookie 相同。舉例來說,假設您要驗證下列已簽署的 Cookie 標頭:
Cookie: Cloud-CDN-Cookie=URLPrefix=URL_PREFIX:Expires=EXPIRATION:KeyName=KEY_NAME:Signature=SIGNATURE; Domain=media.example.com; Path=/; Expires=Tue, 20 Aug 2019 02:26:49 GMT; HttpOnly
可以使用透過 KEY_NAME 命名的 Secret 金鑰,獨立產生簽章,然後驗證該簽章是否與 SIGNATURE 相符。
向使用者簽發 Cookie
應用程式須為每位使用者 (用戶端) 產生並簽發單一 HTTP Cookie,其中包含正確簽署的政策:
在應用程式程式碼中建立 HMAC-SHA-1 簽署者。
使用所選的金鑰簽署政策,並記下新增至後端的金鑰名稱,例如
mySigningKey。依照下列格式建立 Cookie 政策,注意名稱和值皆區分大小寫:
Name: Cloud-CDN-Cookie Value: URLPrefix=$BASE64URLECNODEDURLORPREFIX:Expires=$TIMESTAMP:KeyName=$KEYNAME:Signature=$BASE64URLENCODEDHMAC
Set-Cookie標頭範例:Set-Cookie: Cloud-CDN-Cookie=URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv:Expires=1566268009:KeyName=mySigningKey:Signature=0W2xlMlQykL2TG59UZnnHzkxoaw=; Domain=media.example.com; Path=/; Expires=Tue, 20 Aug 2019 02:26:49 GMT; HttpOnly
Cookie 中的
Domain和Path屬性,決定了用戶端是否將 Cookie 傳送至 Cloud CDN。
建議和必要操作
請明確設定
Domain及Path屬性,須與用於提供受保護內容的網域和路徑前置字元一致,但可能與簽發 Cookie 的網域和路徑不同 (example.com與media.example.com或/browse與/videos)。請確認同一個
Domain和Path底下,指定相同名稱的 Cookie 只有一個。請確認您簽發的 Cookie 沒有衝突,否則可能會導致其他瀏覽器工作階段 (視窗或分頁) 無法存取內容。
適用情況下可設定
Secure和HttpOnly旗標。Secure可確保只透過 HTTPS 連線傳送 Cookie。HttpOnly可防止 JavaScript 存取 Cookie。Cookie 屬性
Expires和Max-Age為選用項目,如果省略這些屬性,只有在瀏覽器工作階段 (分頁、視窗) 存在期間,Cookie 才會存在。快取填補或快取失敗時,已簽署的 Cookie 會傳遞至後端服務中定義的來源。提供內容前,請務必先對每項要求驗證已簽署的 Cookie 值。