

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 設定安全存取和限制對內容的存取
<a name="SecurityAndPrivateContent"></a>

CloudFront 提供數個選項來保護其傳遞內容的安全。以下是一些可用 CloudFront 來保護和限制內容存取的方法：
+ 設定 HTTPS 連線
+ 防止特定地理位置的使用者存取內容
+ 請求使用者使用 CloudFront 已簽署的 URL 或已簽署的 Cookie 來存取內容
+ 設定特定內容欄位的欄位層級加密
+ 使用 AWS WAF 控制對內容的存取

您也應該為您的基礎設施和應用程式實作 DDoS 彈性架構。如需詳細資訊，請參閱 [AWS DDoS 備援的最佳實務](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/aws-best-practices-ddos-resiliency.html)。

如需其他資訊，請參閱以下內容：
+ [使用 CloudFront 保護您的內容交付](https://aws.amazon.com/cloudfront/security/)
+ [Amazon OpenSearch Service 上的 SIEM](https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/README.md)

**Topics**
+ [透過 CloudFront 使用 HTTPS](using-https.md)
+ [使用備用網域名稱和 HTTPS](using-https-alternate-domain-names.md)
+ [使用 CloudFront 進行相互 TLS 身分驗證 （檢視器 mTLS)](mtls-authentication.md)
+ [原始伺服器與 CloudFront 的交互 TLS](origin-mtls-authentication.md)
+ [使用已簽署 URL 和已簽署 Cookie 提供私有內容](PrivateContent.md)
+ [限制對 AWS 原始伺服器的存取](private-content-restricting-access-to-origin.md)
+ [限制對 Application Load Balancers 的存取](restrict-access-to-load-balancer.md)
+ [限制您內容的地理分佈](georestrictions.md)
+ [使用欄位層級加密來協助保護敏感資料](field-level-encryption.md)

# 透過 CloudFront 使用 HTTPS
<a name="using-https"></a>

您可以設定 CloudFront 請求檢視器使用 HTTPS，如此當 CloudFront 與檢視器進行通訊時，連線即可加密。您也可以設定 CloudFront 使用 HTTPS 與原始伺服器連線，如此當 CloudFront 與原始伺服器進行通訊時，連線即可加密。

如果您設定 CloudFront 請求 HTTPS 皆與檢視器和原始伺服器通訊，以下是 CloudFront 接收請求時會發生的情況：

1. 檢視器提交一個 HTTPS 請求給 CloudFront。檢視器和 CloudFront 之間有一些 SSL/TLS 溝通。最後，檢視器以加密格式提交請求。

1. 如果 CloudFront 節點包含快取的回應，則 CloudFront 會加密回應，並將其傳回檢視器，由檢視器進行解密。

1. 如果 CloudFront 節點未包含快取的回應，則 CloudFront 會執行與原始伺服器的 SSL/TLS 溝通，當溝通完成時，以加密格式將請求轉傳給原始伺服器。

1. 原始伺服器會解密請求、處理請求 (產生回應)、加密回應，並將回應傳回 CloudFront。

1. CloudFront 會解密回應、重新加密，以及將其轉傳給檢視器。CloudFront 還會在節點快取回應，以便在下次請求時可以使用該回應。

1. 檢視器解密回應。

無論您的原始伺服器是 Amazon S3 儲存貯體、MediaStore 或自訂原始伺服器，例如 HTTP/S 伺服器，程序基本上都以相同的方式運作：

**注意**  
為了協助阻止 SSL 重新交涉類型攻擊，CloudFront 並不支援檢視器和原始伺服器請求的重新交涉。

或者，您可以為 CloudFront 分佈開啟交互身分驗證。如需詳細資訊，請參閱[使用 CloudFront 進行相互 TLS 身分驗證 （檢視器 mTLS)原始伺服器與 CloudFront 的交互 TLS](mtls-authentication.md)。

如需如何在檢視器和 CloudFront 之間，以及在 CloudFront 和原始伺服器之間使用 HTTPS 的相關資訊，請參閱下列主題。

**Topics**
+ [檢視器和 CloudFront 之間需使用 HTTPS](using-https-viewers-to-cloudfront.md)
+ [需要 HTTPS 到自訂原始伺服器](using-https-cloudfront-to-custom-origin.md)
+ [需要 HTTPS 與 Amazon S3 原始伺服器通訊](using-https-cloudfront-to-s3-origin.md)
+ [檢視器和 CloudFront 之間支援的通訊協定和密碼](secure-connections-supported-viewer-protocols-ciphers.md)
+ [CloudFront 和原始伺服器之間支援的通訊協定和密碼](secure-connections-supported-ciphers-cloudfront-to-origin.md)

# 檢視器和 CloudFront 之間的通訊需使用 HTTPS
<a name="using-https-viewers-to-cloudfront"></a>

您可以在 CloudFront 分發中設定一或多個快取行為以獲得檢視器與 CloudFront 之間進行通訊所需的 HTTPS。您也可以設定一或多個快取行為以允許 HTTP 和 HTTPS，以便 CloudFront 為某些物件使用 HTTPS，而非為其他物件。組態步驟取決於您在物件 URL 中使用哪個網域名稱：
+ 如果您使用 CloudFront 指派給分發的網域名稱，例如 d111111abcdef8.cloudfront.net，請您變更一或多個快取行為的 **檢視器通訊協定原則**設定，使用 HTTPS 通訊。在該組態，CloudFront 提供 SSL/TLS 憑證。

  若要使用 CloudFront 主控台來變更 **檢視器通訊協定原則**的值，請參閱本節稍後說明的步驟。

  如需如何使用 CloudFront API 變更 `ViewerProtocolPolicy` 元素值的詳細資訊，請參閱 *Amazon CloudFront API 參考*中的 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。
+ 如果您使用自己的網域名稱，如 example.com，則您需要變更多種 CloudFront 設定。您也需要使用 AWS Certificate Manager (ACM) 提供的 SSL/TLS 憑證，或是從第三方憑證授權機構或 IAM 憑證存放區將憑證匯入至 ACM。如需詳細資訊，請參閱 [使用備用網域名稱和 HTTPS](using-https-alternate-domain-names.md)。

**注意**  
如果您想要確保檢視器從 CloudFront 取得的物件是否加密，當 CloudFront 從您的原始伺服器取得他們時，請一律使用 CloudFront 與原始伺服器間的 HTTPS。如果您最近在 CloudFront 與原始伺服器之間從 HTTP 變更到 HTTPS，我們建議您使 CloudFront 節點中的物件失效。CloudFront 會將物件傳回到檢視器，無論檢視器使用的通訊協定 (HTTP 或 HTTPS) 與 CloudFront 用來取得物件的通訊協定是否相符。如需有關移除或替換分佈中物件的詳細資訊，請參閱[新增、移除或取代 CloudFront 分配的內容](AddRemoveReplaceObjects.md)。

## 檢視器需要 HTTPS
<a name="configure-cloudfront-HTTPS-viewers"></a>

若要在一或多個快取行為的檢視器與 CloudFront 之間使用 HTTPS，請執行下列程序。<a name="using-https-viewers-to-cloudfront-procedure"></a>

**若要將 CloudFront 設定為在檢視器與 CloudFront 之間請求使用 HTTPS**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在 CloudFront 主控台的頂端窗格中，請選擇您要更新的分發 ID。

1. 在**行為**索引標籤中，選擇您要更新的快取行為，然後選擇**編輯**。

1. 請針對**檢視器通訊協定政策**指定下列其中一個值：  
**重新導向 HTTP 到 HTTPS**  
檢視器可以使用這兩種通訊協定。自動將 HTTP `GET` 和 `HEAD` 請求重新導向到 HTTPS 請求。CloudFront 傳回 HTTP 狀態碼 301 (永久移動) 與新的 HTTPS URL。然後檢視器使用 HTTPS URL 重新將請求提交到 CloudFront。  
如果您使用 HTTP 通過 HTTP 將 `POST`、`PUT`、`DELETE`、`OPTIONS` 或 `PATCH` 傳送到 HTTPS 快取行為和 HTTP 1.1 或更新的請求協定版本，則 CloudFront 請求將重新導向到有 HTTP 狀態碼 307 (暫時重新導向) 的 HTTPS 位置。這可確保再次將請求傳送到使用相同方法與內容承載的新位置。  
如果您通過 HTTP 將 `POST`、`PUT`、`DELETE`、`OPTIONS` 或 `PATCH` 請求傳送到具有請求通訊版本低於 HTTP 1.1 的 HTTPS，則 CloudFront 會傳回 HTTP 狀態碼 403 (禁止)。
當檢視器執行一個 HTTP 請求供其重新導向到 HTTPS 請求時，CloudFront 會收取這兩個請求的費用。針對 HTTP 請求，只會收取 CloudFront 傳回到檢視器的請求與標頭之費用。針對 HTTPS 請求，會收取該請求與原始伺服器傳回的標頭及物件之費用。  
**僅限 HTTPS**  
檢視器只能在使用 HTTPS 的情況下存取您的內容。如果檢視器傳送 HTTP 請求，而不是 HTTPS 請求，則 CloudFront 傳回 HTTP 狀態碼 403 (禁止)，且不會傳回物件。

1. 選擇**儲存變更**。

1. 對於您希望在檢視器和 CloudFront 間需要使用 HTTPS 的每一個額外快取行為，重複步驟 3 至 5。

1. 您使用生產環境中已更新的組態之前，請先確認以下項目：
   + 每個快取行為中的路徑模式僅適用於您想要檢視器使用 HTTPS 的請求。
   + 以您想要 CloudFront 評估的順序列出快取行為。如需詳細資訊，請參閱 [路徑模式](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)。
   + 快取行為會將請求路由到正確的原始伺服器。

# 要求 CloudFront 與自訂原始伺服器之間的通訊使用 HTTPS
<a name="using-https-cloudfront-to-custom-origin"></a>

您可以要求 CloudFront 與自訂原始伺服器之間的通訊使用 HTTPS。

**注意**  
如果您的原始伺服器是設定為網站端點的 Amazon S3 儲存貯體，則無法設定 CloudFront 使用 HTTPS 來與原始伺服器通訊，因為 Amazon S3 不支援網站端點的 HTTPS。

若要在 CloudFront 與原始伺服器之間要求使用 HTTPS，請依照本主題中的程序執行下列步驟：

1. 在您的分佈中，針對原始伺服器變更其 **Origin Protocol Policy** (原始伺服器通訊協定政策) 設定。

1. 在您的原始伺服器安裝 SSL/TLS 憑證 （當您使用 Amazon S3 原始伺服器或其他特定 AWS 原始伺服器時，不需要此操作）。

**Topics**
+ [自訂原始伺服器需要 HTTPS](#using-https-cloudfront-to-origin-distribution-setting)
+ [在您的自訂原始伺服器上安裝 SSL/TLS 憑證](#using-https-cloudfront-to-origin-certificate)

## 自訂原始伺服器需要 HTTPS
<a name="using-https-cloudfront-to-origin-distribution-setting"></a>

下列程序說明如何設定 CloudFront 使用 HTTPS 與 Elastic Load Balancing 負載平衡器、Amazon EC2 執行個體或其他自訂原始伺服器原始伺服器進行通訊。如需使用 CloudFront API 更新分佈的詳細資訊，請參閱 *Amazon CloudFront API 參考*中的 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。<a name="using-https-cloudfront-to-custom-origin-procedure"></a>

**設定 CloudFront 在 CloudFront 和您的自訂原始伺服器間需使用 HTTPS**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在 CloudFront 主控台的頂端窗格中，請選擇您要更新的分發 ID。

1. 在**行為**索引標籤中，選擇您要更新的原始伺服器，然後選擇**編輯**。

1. 更新下列設定：  
**原始伺服器通訊協定政策**  
針對您分佈中適用的原始伺服器，變更其 **Origin Protocol Policy (原始伺服器通訊協定政策)**：  
   + **僅限 HTTPS** – CloudFront 只會使用 HTTPS 來和自訂原始伺服器進行通訊。
   + **比對檢視器** – CloudFront 會根據檢視器請求的通訊協定，使用 HTTP 或 HTTPS 與您的原始伺服器進行通訊。例如，如果您為**原始伺服器通訊協定原則**選擇**比對檢視器**，且檢視器使用 HTTPS 從 CloudFront 要求一個物件，則 CloudFront 也使用 HTTPS 將請求轉送到原始伺服器。

     只有針對 **Viewer Protocol Policy (檢視器通訊協定政策)** 指定 **Redirect HTTP to HTTPS (將 HTTP 重新導向至 HTTPS)** 或 **HTTPS Only (僅限 HTTPS)** 時，才能選擇 **Match Viewer (配合檢視器)**。

     請注意 CloudFront 僅會在檢視器使用 HTTP 和 HTTPS 協定發出請求時，快取物件一次。  
**原始伺服器 SSL 通訊協定**  
針對分佈中適用的原始伺服器，選擇 **Origin SSL Protocols (原始伺服器 SSL 通訊協定)**。SSLv3 通訊協定較不安全，因此我們建議您只有在原始伺服器不支援 TLSv1 或新版本時，選擇 SSLv3。TLSv1 交握與 SSLv3 有回溯相容與正向相容，但 TLSv1.1 和後續版本則無。當您選擇 SSLv3 時，CloudFront *只會*傳送 SSLv3 交握請求。

1. 選擇**儲存變更**。

1. 對於您希望在 CloudFront 和自訂原始伺服器間需要使用 HTTPS 的每一個額外原始伺服器，重複步驟 3 至 5。

1. 您使用生產環境中已更新的組態之前，請先確認以下項目：
   + 每個快取行為中的路徑模式僅適用於您想要檢視器使用 HTTPS 的請求。
   + 以您想要 CloudFront 評估的順序列出快取行為。如需詳細資訊，請參閱 [路徑模式](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)。
   + 快取行為會將請求轉傳到您已變更其 **Origin Protocol Policy (原始伺服器通訊協定政策)** 的原始伺服器。

## 在您的自訂原始伺服器上安裝 SSL/TLS 憑證
<a name="using-https-cloudfront-to-origin-certificate"></a>

在自訂原始伺服器上，您可以從以下來源使用 SSL/TLS 憑證：
+ 如果您的原始伺服器是 Elastic Load Balancing 負載平衡器，則可以使用 AWS Certificate Manager (ACM) 提供的憑證。您也可以使用信任第三方憑證授權單位簽署的憑證並匯入 ACM。
+ 針對 Elastic Load Balancing 負載平衡器以外的原始伺服器，您必須使用信任第三方憑證授權機構 (CA) 簽署的憑證，例如 Comodo、DigiCert 或 Symantec。

從原始伺服器傳回的憑證必須包含下列其中一個網域名稱：
+ 原始伺服器的 **Origin domain** (原始伺服器網域) 欄位 (CloudFront API 中的 `DomainName` 欄位) 中的網域名稱。
+ 如果快取行為已設定為轉發 `Host` 標頭至原始伺服器，則為 `Host` 標頭中的網域名稱。

當 CloudFront 使用 HTTPS 與您的原始伺服器通訊時，CloudFront 驗證信任憑證授權機構發出的憑證。CloudFront 支援與 Mozilla 相同的憑證授權機構。如需目前的清單，請參閱 [Mozilla Included CA Certificate List](https://wiki.mozilla.org/CA/Included_Certificates)。您無法使用自我簽署憑證進行 CloudFront 和原始伺服器之間的 HTTPS 通訊。

**重要**  
如果該原始伺服器傳回過期憑證、無效憑證，或自我簽署憑證，或者，如果原始伺服器傳回順序錯誤的憑證鍊，則 CloudFront 失去 TCP 連線、傳回 HTTP 狀態碼 502 (無效的閘道) 至檢視者，並將 `X-Cache` 標頭設定為 `Error from cloudfront`。此外，若完整的憑證鏈結 (包含中繼憑證) 不存在，CloudFront 便會卸除 TCP 連線。

# 請求使用 HTTPS 在 CloudFront 與您的 Amazon S3 原始伺服器之間進行通訊
<a name="using-https-cloudfront-to-s3-origin"></a>

當您的原始伺服器是 Amazon S3 bucket 儲存貯體，您能否選擇使用 HTTPS 與 CloudFront 通訊，取決於您使用儲存貯體的方式。如果設定 Amazon S3 儲存貯體為網站端點，則您無法設定 CloudFront 使用 HTTPS 與原始伺服器進行通訊，因為 Amazon S3 在該組態中不支援 HTTPS 連線。

如果您的原始伺服器是支援 HTTPS 通訊的 Amazon S3 儲存貯體，則 CloudFront 會使用檢視器用來提交請求的通訊協定，來將請求轉送到 S3。[通訊協定 (僅限自訂原始伺服器)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginProtocolPolicy) 設定的預設為**比對檢視器**，而且無法變更。不過如果您為 Amazon S3 原始伺服器啟用原始存取控制 (OAC)，CloudFront 和 Amazon S3 之間使用的通訊將取決於您的設定。如需詳細資訊，請參閱[建立新的原始存取控制](private-content-restricting-access-to-s3.md#create-oac-overview-s3)。

如果您要使用 HTTPS 進行 CloudFront 與 Amazon S3 之間的通訊，必須變更 **檢視器通訊協定原則**的值為**重新導向 HTTP 到 HTTPS** 或 **僅限 HTTP**。本節稍後的步驟，說明如何使用 CloudFront 主控台來變更**檢視器通訊協定原則**。如需使用 CloudFront API 來更新分佈 `ViewerProtocolPolicy` 元素的詳細資訊，請參閱 *Amazon CloudFront API 參考*中的 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。

當您搭配支援 HTTPS 通訊的 Amazon S3 儲存貯體使用 HTTPS 時，Amazon S3 會提供 SSL/TLS 憑證，您則不需要。

## Amazon S3 原始伺服器需要 HTTPS
<a name="configure-cloudfront-HTTPS-S3-origin"></a>

下列程序示範如何設定 CloudFront，以要求使用 HTTPS 與您的 Amazon S3 原始伺服器通訊。<a name="using-https-cloudfront-to-s3-origin-procedure"></a>

**若要將 CloudFront 設定為請求使用 HTTPS 連線到您的 Amazon S3 原始伺服器**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在 CloudFront 主控台的頂端窗格中，請選擇您要更新的分發 ID。

1. 在 **Behaviors (行為)** 索引標籤中，選擇您要更新的快取行為，然後選擇 **Edit (編輯)**。

1. 請針對 **Viewer Protocol Policy (檢視器通訊協定政策)** 指定下列其中一個值：  
**重新引導 HTTP 到 HTTPS**  
檢視器可以使用這兩種通訊協定，但會自動重新導向 HTTP 請求到 HTTPS 請求。CloudFront 傳回 HTTP 狀態碼 301 (永久移動) 與新的 HTTPS URL。然後檢視器使用 HTTPS URL 重新將請求提交到 CloudFront。  
CloudFront 不會從 HTTP 將 `DELETE`、`OPTIONS`、`PATCH`、`POST` 或 `PUT` 請求重新引導到 HTTPS。如果您配置快取行為重新導向至 HTTPS，則 CloudFront 回應該快取行為的 HTTP `DELETE`、`OPTIONS`、`PATCH`、`POST` 或 `PUT` 請求，此快取行為具有 HTTP 狀態碼 403 (禁止)。
當檢視器執行一個 HTTP 請求供其重新導向到 HTTPS 請求時，CloudFront 會收取這兩個請求的費用。針對 HTTP 請求，只會收取 CloudFront 傳回到檢視器的請求與標頭之費用。針對 HTTPS 請求，會收取該請求與標頭及原始伺服器傳回的物件之費用。  
**僅限 HTTPS**  
檢視器只能在使用 HTTPS 的情況下存取您的內容。如果檢視器傳送 HTTP 請求，而不是 HTTPS 請求，則 CloudFront 傳回 HTTP 狀態碼 403 (禁止)，且不會傳回物件。

1. 請選擇 **Yes, Edit (是，編輯)**。

1. 為每個額外快取行為，供您要在檢視器與 CloudFront 之間以及 CloudFront 與 S3 之間使用 HTTPS，請重複步驟 3 到 5。

1. 您使用生產環境中已更新的組態之前，請先確認以下項目：
   + 每個快取行為中的路徑模式僅適用於您想要檢視器使用 HTTPS 的請求。
   + 以您想要 CloudFront 評估的順序列出快取行為。如需詳細資訊，請參閱 [路徑模式](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)。
   + 快取行為會將請求路由到正確的原始伺服器。

# 檢視器和 CloudFront 之間支援的通訊協定和密碼
<a name="secure-connections-supported-viewer-protocols-ciphers"></a>

當您[在檢視器和 CloudFront 分佈之間請求 HTTPS 時](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)，您必須選擇[安全性政策](DownloadDistValuesGeneral.md#DownloadDistValues-security-policy)，以決定下列設定。
+ CloudFront 用來與檢視者通訊的最低 SSL/TLS 通訊協定。
+ CloudFront 可用來加密與檢視器通訊的密碼。

若要選擇安全政策，請指定適用於 [安全政策 (最低 SSL/TLS 版本)](DownloadDistValuesGeneral.md#DownloadDistValues-security-policy) 的適用值。下表列出 CloudFront 可以用於每個安全原則的協定與密碼。

檢視器必須支援至少一個受支援的密碼，建立與 CloudFront 的 HTTPS 連線。CloudFront 從檢視器支援的密碼中依列出的順序選擇密碼。另請參閱[OpenSSL、S2n 和 RFC 密碼名稱](#secure-connections-openssl-rfc-cipher-names)。


|  | 安全政策 |  | SSLv3 | TLSv1 | TLSv1\$12016 | TLSv1.1\$12016 | TLSv1.2\$12018 | TLSv1.2\$12019 | TLSv1.2\$12021 | TLSv1.2\$12025 | TLSv1.3\$12025 | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 支援的 SSL/TLS 通訊協定 | 
| TLSv1.3 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLSv1.2 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | 
| TLSv1.1 | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| TLSv1 | ♦ | ♦ | ♦ |  |  |  |  |  |  | 
| SSLv3 | ♦ |  |  |  |  |  |  |  |  | 
| 支援的 TLSv1.3 密碼 | 
| TLS\$1AES\$1128\$1GCM\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1AES\$1256\$1GCM\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1CHACHA20\$1POLY1305\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | ♦ | 
| 支援的 ECDSA 密碼 | 
| ECDHE-ECDSA-AES128-GCM-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | 
| ECDHE-ECDSA-AES128-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  | 
| ECDHE-ECDSA-AES128-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| ECDHE-ECDSA-AES256-GCM-SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | 
| ECDHE-ECDSA-CHACHA20-POLY1305 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  | 
| ECDHE-ECDSA-AES256-SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  | 
| ECDHE-ECDSA-AES256-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| 支援的 RSA 密碼 | 
| ECDHE-RSA-AES128-GCM-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | 
| ECDHE-RSA-AES128-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  | 
| ECDHE-RSA-AES128-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| ECDHE-RSA-AES256-GCM-SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  | 
| ECDHE-RSA-CHACHA20-POLY1305 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  | 
| ECDHE-RSA-AES256-SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  | 
| ECDHE-RSA-AES256-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| AES128-GCM-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  |  | 
| AES256-GCM-SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  |  | 
| AES128-SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ |  |  |  |  | 
| AES256-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| AES128-SHA | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| DES-CBC3-SHA | ♦ | ♦ |  |  |  |  |  |  |  | 
| RC4-MD5 | ♦ |  |  |  |  |  |  |  |  | 

## OpenSSL、S2n 和 RFC 密碼名稱
<a name="secure-connections-openssl-rfc-cipher-names"></a>

penSSL and [s2n](https://github.com/awslabs/s2n) 會使用與 TLS 標準不同的密碼名稱 ([RFC 2246](https://tools.ietf.org/html/rfc2246)、[RFC 4346](https://tools.ietf.org/html/rfc4346)、[RFC 5246](https://tools.ietf.org/html/rfc5246) 和 [RFC 8446](https://tools.ietf.org/html/rfc8446))。下表將 OpenSSL 和 s2n 名稱對應到每個密碼的 RFC 名稱。

CloudFront 支援傳統和量子安全金鑰交換。對於使用橢圓曲線的傳統金鑰交換，CloudFront 支援下列項目：
+ `prime256v1`
+ `X25519`
+ `secp384r1`

對於保護量子的金鑰交換，CloudFront 支援下列項目：
+ `X25519MLKEM768`
+ `SecP256r1MLKEM768`
**注意**  
TLS 1.3 僅支援 Quantum 安全金鑰交換。TLS 1.2 和舊版不支援規定人數安全金鑰交換。

  如需詳細資訊，請參閱下列主題：
  + [後量子密碼學](https://aws.amazon.com/security/post-quantum-cryptography/)
  + [密碼編譯演算法和 AWS 服務](https://docs.aws.amazon.com/prescriptive-guidance/latest/encryption-best-practices/aws-cryptography-services.html#algorithms)
  + [TLS 1.3 中的混合金鑰交換](https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/)

如需 CloudFront 憑證需求的詳細資訊，請參閱 [與 CloudFront 搭配使用 SSL/TLS 憑證的要求](cnames-and-https-requirements.md)。


| OpenSSL 和 s2n 密碼名稱 | RFC 密碼名稱 | 
| --- | --- | 
| 支援的 TLSv1.3 密碼 | 
| TLS\$1AES\$1128\$1GCM\$1SHA256 | TLS\$1AES\$1128\$1GCM\$1SHA256 | 
| TLS\$1AES\$1256\$1GCM\$1SHA384 | TLS\$1AES\$1256\$1GCM\$1SHA384 | 
| TLS\$1CHACHA20\$1POLY1305\$1SHA256 | TLS\$1CHACHA20\$1POLY1305\$1SHA256 | 
| 支援的 ECDSA 密碼 | 
| ECDHE-ECDSA-AES128-GCM-SHA256 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-ECDSA-AES128-SHA256 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| ECDHE-ECDSA-AES128-SHA | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| ECDHE-ECDSA-AES256-GCM-SHA384 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| ECDHE-ECDSA-CHACHA20-POLY1305 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1CHACHA20\$1POLY1305\$1SHA256 | 
| ECDHE-ECDSA-AES256-SHA384 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384 | 
| ECDHE-ECDSA-AES256-SHA | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| 支援的 RSA 密碼 | 
| ECDHE-RSA-AES128-GCM-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-RSA-AES128-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256  | 
| ECDHE-RSA-AES128-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| ECDHE-RSA-AES256-GCM-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384  | 
| ECDHE-RSA-CHACHA20-POLY1305 | TLS\$1ECDHE\$1RSA\$1WITH\$1CHACHA20\$1POLY1305\$1SHA256 | 
| ECDHE-RSA-AES256-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384  | 
| ECDHE-RSA-AES256-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-GCM-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| AES256-GCM-SHA384 | TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| AES128-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| AES256-SHA | TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-SHA | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| DES-CBC3-SHA  | TLS\$1RSA\$1WITH\$13DES\$1EDE\$1CBC\$1SHA  | 
| RC4-MD5 | TLS\$1RSA\$1WITH\$1RC4\$1128\$1MD5 | 

## 檢視器和檢視器之間支援的簽名結構描述和 CloudFront
<a name="secure-connections-viewer-signature-schemes"></a>

CloudFront 支援下列簽名結構描述，用於與檢視器之間的連結和 CloudFront。


|  | 安全政策 | 簽章結構描述 | SSLv3 | TLSv1 | TLSv1\$12016 | TLSv1.1\$12016 | TLSv1.2\$12018 | TLSv1.2\$12019 |  TLSv1.2\$12021 | TLSv1.2\$12025 | TLSv1.3\$12025 | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1PSS\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1PSS\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1PSS\$1SHA512 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1RSAE\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1RSAE\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PSS\$1RSAE\$1SHA512 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA512 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA224 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA512 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA224 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ |  |  | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SECP256R1\$1SHA256 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SECP384R1\$1SHA384 | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | ♦ | 
| TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA1 | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 
| TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA1 | ♦ | ♦ | ♦ | ♦ |  |  |  |  |  | 

# CloudFront 和原始伺服器之間支援的通訊協定和密碼
<a name="secure-connections-supported-ciphers-cloudfront-to-origin"></a>

如果您選擇[請求在 CloudFront 與原始伺服器之間使用 HTTPS](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginProtocolPolicy)，則可以決定[允許使用哪種 SSL/TLS 通訊協定](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginSSLProtocols)來進行安全的連線，然後 CloudFront 可以使用下方表格中列出的任何 ECDSA 或 RSA 密碼，連線至原始伺服器。您的原始伺服器必須支援至少一種 CloudFront 密碼，才能建立與原始伺服器的 HTTPS 連線。

penSSL and [s2n](https://github.com/awslabs/s2n) 會使用與 TLS 標準不同的密碼名稱 ([RFC 2246](https://tools.ietf.org/html/rfc2246)、[RFC 4346](https://tools.ietf.org/html/rfc4346)、[RFC 5246](https://tools.ietf.org/html/rfc5246) 和 [RFC 8446](https://tools.ietf.org/html/rfc8446))。下表將包含每種密碼的 OpenSSL 和 s2n 名稱以及 RFC 名稱。

對於具有橢圓曲線金鑰交換演算法的密碼，CloudFront 支援下列橢圓曲線：
+ prime256v1
+ secp384r1
+ X25519


| OpenSSL 和 s2n 密碼名稱 | RFC 密碼名稱 | 
| --- | --- | 
| 支援的 ECDSA 密碼 | 
| ECDHE-ECDSA-AES256-GCM-SHA384 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| ECDHE-ECDSA-AES256-SHA384 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384 | 
| ECDHE-ECDSA-AES256-SHA | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| ECDHE-ECDSA-AES128-GCM-SHA256 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-ECDSA-AES128-SHA256 | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| ECDHE-ECDSA-AES128-SHA | TLS\$1ECDHE\$1ECDSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| 支援的 RSA 密碼 | 
| ECDHE-RSA-AES256-GCM-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| ECDHE-RSA-AES256-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384 | 
| ECDHE-RSA-AES256-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| ECDHE-RSA-AES128-GCM-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-RSA-AES128-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| ECDHE-RSA-AES128-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| AES256-SHA | TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-SHA | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| DES-CBC3-SHA | TLS\$1RSA\$1WITH\$13DES\$1EDE\$1CBC\$1SHA | 
| RC4-MD5 | TLS\$1RSA\$1WITH\$1RC4\$1128\$1MD5 | 

**CloudFront 與原始伺服器之間支援的簽名方案**

CloudFront 支援下列簽署設定，用於 CloudFront 和原始伺服器之間的連線。
+ TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA256
+ TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA384
+ TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA512
+ TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA224
+ TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA256
+ TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA384
+ TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA512
+ TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA224
+ TLS\$1SIGNATURE\$1SCHEME\$1RSA\$1PKCS1\$1SHA1
+ TLS\$1SIGNATURE\$1SCHEME\$1ECDSA\$1SHA1

# 使用備用網域名稱和 HTTPS
<a name="using-https-alternate-domain-names"></a>

若您想要在檔案的 URL 中使用自己的網域名稱 (例如 `https://www.example.com/image.jpg`)，並希望您的檢視器使用 HTTPS，則必須完成下列主題的步驟。(如果您在 URL 中使用預設的 CloudFront 分佈網域名稱，例如 `https://d111111abcdef8.cloudfront.net/image.jpg`，請改為遵循下列主題中的指示：[檢視器和 CloudFront 之間的通訊需使用 HTTPS](using-https-viewers-to-cloudfront.md)。)

**重要**  
當您新增憑證到分佈，CloudFront 會立即傳播憑證到其所有節點。隨著新節點變為可用，CloudFront 也會傳播憑證到這些位置。您無法限制 CloudFront 傳播憑證的節點。

**Topics**
+ [選擇 CloudFront 提供 HTTPS 請求的方式](cnames-https-dedicated-ip-or-sni.md)
+ [與 CloudFront 搭配使用 SSL/TLS 憑證的要求](cnames-and-https-requirements.md)
+ [搭配 CloudFront 使用 SSL/TLS 憑證的配額 (僅限檢視器與 CloudFront 之間的 HTTPS)](cnames-and-https-limits.md)
+ [設定備用網域名稱和 HTTPS](cnames-and-https-procedures.md)
+ [判斷 SSL/TLS RSA 憑證中公有金鑰的大小](cnames-and-https-size-of-public-key.md)
+ [增加 SSL/TLS 憑證的配額](increasing-the-limit-for-ssl-tls-certificates.md)
+ [輪換 SSL/TLS 憑證](cnames-and-https-rotate-certificates.md)
+ [從自訂 SSL/TLS 憑證還原到預設 CloudFront 憑證](cnames-and-https-revert-to-cf-certificate.md)
+ [若要從具有專用 IP 位址的自訂 SSL/TLS 憑證切換到 SNI](cnames-and-https-switch-dedicated-to-sni.md)

# 選擇 CloudFront 提供 HTTPS 請求的方式
<a name="cnames-https-dedicated-ip-or-sni"></a>

如果您想要檢視器使用 HTTPS 與使用檔案的備用網域名稱，請選擇以下其中一個選項以決定 CloudFront 如何提供 HTTPS 請求：
+ 使用[伺服器名稱指示 (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) – 推薦
+ 在每個節點使用專用的 IP 位址

本節說明每個選項的運作方式。

## 使用 SNI 提供 HTTPS 請求 (適用於大部分用戶端)
<a name="cnames-https-sni"></a>

[伺服器名稱指示 (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) 是 TLS 通訊協定的延伸，2010 年之後推出的瀏覽器和用戶端支援此選項。如果設定 CloudFront 使用 SNI 來提供 HTTPS 請求，則 CloudFront 會將您的替代網域名稱，與每個節點中的 IP 位址建立關聯。當檢視器提交內容的 HTTPS 請求時，DNS 會將請求路由到正確節點的 IP 位址。您網域名稱的 IP 位址在 SSL/TLS 交握溝通期間決定；IP 位址並非專用於您的分佈。

SSL/TLS 溝通發生在建立 HTTPS 連線的初期。如果 CloudFront 無法立即判斷請求是針對哪些網域，它就會失去連線。當 SNI 支援的檢視器提交內容的 HTTPS 請求時，情況如下：

1. 檢視器會自動從請求 URL 取得網域名稱，並將其新增至 TLS 用戶端 hello 訊息的 SNI 延伸模組。

1. 當 CloudFront 收到 TLS 用戶端 hello 時，它會使用 SNI 延伸模組中的網域名稱來尋找相符的 CloudFront 分佈，並傳回相關聯的 TLS 憑證。

1. 檢視器和 CloudFront 執行 SSL/TLS 交涉。

1. CloudFront 將請求的內容傳回到檢視器。

關於支援 SNI 的瀏覽器，最新的清單請參閱 Wikipedia 條目 [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication) (伺服器名稱指示)。

如果您想要使用 SNI，但某些使用者的瀏覽器不支援 SNI，則您有幾個選項：
+ 設定 CloudFront 使用專用 IP 位址而不是 SNI，提供 HTTPS 請求。如需詳細資訊，請參閱 [使用專用 IP 位址提供 HTTPS 請求 (適用於所有用戶端)](#cnames-https-dedicated-ip)。
+ 使用 CloudFront SSL/TLS 憑證，不使用自訂憑證。這需要您在檔案的 URL 中，使用您分佈的 CloudFront 網域名稱，例如，`https://d111111abcdef8.cloudfront.net/logo.png`。

  如果您使用預設 CloudFront 憑證，檢視器必須支援 SSL 協定 TLSv1 或更新版本。 CloudFront 不支援具有預設 CloudFront 憑證的 SSLv3。

  您也必須將 CloudFront 使用的 SSL/TLS 憑證，從自訂憑證變更為預設的 CloudFront 憑證：
  + 如果您尚未使用分佈來分配內容，可以只變更組態。如需詳細資訊，請參閱 [更新分佈](HowToUpdateDistribution.md)。
  + 如果您已經使用分佈來分配內容，則您必須建立新的 CloudFront 分配和變更檔案的 URL，以降低或消除內容不可用的時間。如需詳細資訊，請參閱 [從自訂 SSL/TLS 憑證還原到預設 CloudFront 憑證](cnames-and-https-revert-to-cf-certificate.md)。
+ 如果您可以控制您的使用者使用哪些瀏覽器，請讓他們升級到支援 SNI 的瀏覽器。
+ 使用 HTTP，而非 HTTPS。

## 使用專用 IP 位址提供 HTTPS 請求 (適用於所有用戶端)
<a name="cnames-https-dedicated-ip"></a>

伺服器名稱指示 (SNI) 是將請求關聯至網域的一個方法。另一個方式是使用專用 IP 位址。如果您有使用者無法升級到 2010 年後推出的瀏覽器或用戶端，您可以使用專用 IP 位址來提供 HTTPS 請求。關於支援 SNI 的瀏覽器，最新的清單請參閱 Wikipedia 條目 [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication) (伺服器名稱指示)。

**重要**  
如果您設定 CloudFront 使用專用 IP 位址提供 HTTPS 請求，您需要支付額外的每月費用。當您把 SSL/TLS 憑證與分佈相關聯並啟用此分佈時，即開始收費。如需 CloudFront 定價的詳細資訊，請參閱 [Amazon CloudFront 定價](https://aws.amazon.com/cloudfront/pricing)。除此之外：請參閱 [Using the Same Certificate for Multiple CloudFront Distributions](cnames-and-https-limits.md#cnames-and-https-same-certificate-multiple-distributions)。

當您設定 CloudFront 為使用專用 IP 位址來提供 HTTPS 請求，CloudFront 會將您的憑證與每個 CloudFront 邊緣節點中的專用 IP 位址建立關聯。當檢視器提交內容的 HTTPS 請求時，情況如下：

1. DNS 將請求路由到適用節點中分佈的 IP 位址。

1. 如果用戶端請求在 `ClientHello` 訊息中提供 SNI 延伸，CloudFront 會搜尋與該 SNI 相關聯的分佈。
   + 如果有相符項目，CloudFront 會使用 SSL/TLS 憑證回應請求。
   + 如果找不到相符項目，CloudFront 將改用 IP 位址識別您的分佈，並判斷要將哪些 SSL/TLS 憑證傳回到檢視器。

1. 檢視器和 CloudFront 使用 SSL/TLS 憑證執行 SSL/TLS 溝通。

1. CloudFront 將請求的內容傳回到檢視器。

這種方式適用於每個 HTTPS 請求，無論使用者使用的是瀏覽器或其他檢視器。

**注意**  
專用 IP 不是靜態 IP，而且可能會隨著時間而變更。為邊緣節點傳回的 IP 位址會從 [CloudFront 邊緣伺服器清單](LocationsOfEdgeServers.md)的 IP 位址範圍動態分配。  
CloudFront 邊緣伺服器的 IP 位址範圍可能變更。若要收到 IP 地址變更的通知，[請透過 Amazon SNS 訂閱 AWS 公有 IP 地址變更](https://aws.amazon.com/blogs/aws/subscribe-to-aws-public-ip-address-changes-via-amazon-sns/)。

## 請求使用三個或更多專用 IP SSL/TLS 憑證的許可
<a name="cnames-and-https-multiple-certificates"></a>

如果您需要三個或多個 SSL/TLS 專用的 IP 憑證與 CloudFront 永久關聯的許可 ，請執行下列程序。如需 HTTPS 請求的詳細資訊，請參閱 [選擇 CloudFront 提供 HTTPS 請求的方式](#cnames-https-dedicated-ip-or-sni)。

**注意**  
此程序用於使用 3 個或多個跨 CloudFront 分佈的專用 IP 憑證時。預設值為 2。請注意，您不可以繫結超過 1 個 SSL 憑證到分佈。  
您一次只能將一個 SSL/TLS 憑證與 CloudFront 分佈相關聯。此數字為您可以跨所有 CloudFront 分佈使用的專用 IP SSL 憑證之總和。<a name="cnames-and-https-multiple-certificates-procedure"></a>

**請求使用具有一個 CloudFront 分佈的三個或多個憑證之許可**

1. 請前往[支援中心](https://console.aws.amazon.com/support/home?#/case/create?issueType=service-limit-increase&limitType=service-code-cloudfront-distributions)並建立案例。

1. 請指出您需要許可才能使用的憑證有多少，以及說明請求中的情況。我們會儘快更新您的帳戶。

1. 請繼續下一個程序。

# 與 CloudFront 搭配使用 SSL/TLS 憑證的要求
<a name="cnames-and-https-requirements"></a>

本主題描述 SSL/TLS 憑證的需求。它們適用於以下兩種情況 (除非另有說明)：
+ 適用於檢視器和 CloudFront 之間使用 HTTPS 的憑證 
+ 適用於 CloudFront 與原始伺服器之間使用 HTTPS 的憑證

**Topics**
+ [憑證發行者](#https-requirements-certificate-issuer)
+ [AWS 區域 適用於 的 AWS Certificate Manager](#https-requirements-aws-region)
+ [憑證格式](#https-requirements-certificate-format)
+ [中繼憑證](#https-requirements-intermediate-certificates)
+ [Key type](#https-requirements-key-type)
+ [私有金鑰](#https-requirements-private-key)
+ [許可](#https-requirements-permissions)
+ [憑證金鑰的大小](#https-requirements-size-of-public-key)
+ [支援的憑證類型](#https-requirements-supported-types)
+ [憑證過期日期和續約](#https-requirements-cert-expiration)
+ [CloudFront 分佈和憑證中的網域名稱](#https-requirements-domain-names-in-cert)
+ [最低 SSL/TLS 通訊協定版本](#https-requirements-minimum-ssl-protocol-version)
+ [支援的 HTTP 版本](#https-requirements-supported-http-versions)

## 憑證發行者
<a name="https-requirements-certificate-issuer"></a>

我們建議您使用由 [AWS Certificate Manager (ACM)](https://aws.amazon.com/certificate-manager/) 出具的憑證。如需有關如何從 ACM 取得憑證的資訊，請參閱 *[AWS Certificate Manager 使用者指南](https://docs.aws.amazon.com/acm/latest/userguide/)*。若要搭配 CloudFront 分佈使用 ACM 憑證，請確定您是在美國東部 (維吉尼亞北部) 區域 (`us-east-1`) 請求 (或匯入) 憑證。

 CloudFront 支援與 Mozilla 相同的憑證授權機構 (CA)，因此如果您不使用 ACM，請使用由 [Mozilla 所含憑證授權機構憑證清單](https://wiki.mozilla.org/CA/Included_Certificates)上的 CA 發行的憑證。

您為 CloudFront 分佈指定的原始伺服器所使用的 TLS 憑證也需要從 Mozilla 包含 CA 憑證清單上的 CA 發行。

如需有關如何取得和安裝憑證的詳細資訊，請參閱 HTTP 伺服器軟體的文件和 CA 的文件。

## AWS 區域 適用於 的 AWS Certificate Manager
<a name="https-requirements-aws-region"></a>

若要在 AWS Certificate Manager (ACM) 中使用憑證來要求檢視器和 CloudFront 之間的 HTTPS，請務必在美國東部 （維吉尼亞北部） 區域 () 請求 （或匯入） 憑證`us-east-1`。

如果您想要在 CloudFront 和原始伺服器之間要求 HTTPS，而且您正在使用 Elastic Load Balancing 中的負載平衡器做為原始伺服器，您可以在任何 中請求或匯入憑證 AWS 區域。

## 憑證格式
<a name="https-requirements-certificate-format"></a>

憑證必須為 X.509 PEM 格式。如果您使用 AWS Certificate Manager，這是預設格式。

## 中繼憑證
<a name="https-requirements-intermediate-certificates"></a>

如果您使用第三方憑證授權機構 (CA)，請在列出位於 `.pem` 檔案的憑證鏈中的所有中繼憑證，從為您網域簽屬憑證的 CA 開始。一般而言，您可以在 CA 網站上找到以適當鏈結順序列出中繼和根憑證的檔案。

**重要**  
不包括下列項目：根憑證、不在信任路徑的中繼憑證，或您 CA 的公有金鑰憑證。

範例如下：

```
-----BEGIN CERTIFICATE-----
Intermediate certificate 2
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Intermediate certificate 1
-----END CERTIFICATE-----
```

## Key type
<a name="https-requirements-key-type"></a>

CloudFront 支援 RSA 和公有/私有金鑰對。

CloudFront 支援使用 RSA 和 ECDSA 憑證與檢視器和原始伺服器進行 HTTPS 連線。搭配 [AWS Certificate Manager (ACM)](https://console.aws.amazon.com/acm)，您可以請求和匯入 RSA 或 ECDSA 憑證，然後將它們與 CloudFront 分佈建立關聯。

如需可在 HTTPS 連線中交涉之 CloudFront 所支援的 RSA 和 ECDSA 密碼清單，請參閱[檢視器和 CloudFront 之間支援的通訊協定和密碼](secure-connections-supported-viewer-protocols-ciphers.md)和[CloudFront 和原始伺服器之間支援的通訊協定和密碼](secure-connections-supported-ciphers-cloudfront-to-origin.md)。

## 私有金鑰
<a name="https-requirements-private-key"></a>

如果您從第三方憑證授權單位 (CA) 使用憑證，請注意以下事項：
+ 私有金鑰必須符合憑證中的公有金鑰。
+ 私有金鑰必須是 PEM 格式。
+ 無法用密碼加密私有金鑰。

如果 AWS Certificate Manager (ACM) 提供憑證，ACM 不會釋出私有金鑰。私有金鑰存放在 ACM 中，供與 ACM 整合的 AWS 服務使用。

## 許可
<a name="https-requirements-permissions"></a>

您必須具有使用和匯入 SSL/TLS 憑證的許可。如果您使用的是 AWS Certificate Manager (ACM)，我們建議您使用 AWS Identity and Access Management 許可來限制對憑證的存取。如需詳細資訊，請參閱 *AWS Certificate Manager 使用者指南*中的 [Identity and Access Management](https://docs.aws.amazon.com/acm/latest/userguide/security-iam.html)。

## 憑證金鑰的大小
<a name="https-requirements-size-of-public-key"></a>

CloudFront 支援的憑證金鑰大小取決於金鑰和憑證的類型。

**對於 RSA 憑證：**  
CloudFront 支援 1024 位元、2048 位元、3072 位元和 4096 位元 RSA 金鑰。與 CloudFront 搭配使用的 RSA 憑證，其金鑰長度上限為 4096 位元。  
 請注意，ACM 發行的 RSA 憑證最多擁有 2048 位元金鑰。若要使用 3072 位元或 4096 位元的 RSA 憑證，您需要從外部取得憑證並將其匯入 ACM，之後即可和 CloudFront 搭配使用。  
如需有關如何判斷 RSA 金鑰大小的詳細資訊，請參閱[判斷 SSL/TLS RSA 憑證中公有金鑰的大小](cnames-and-https-size-of-public-key.md)。

**對於 ECDSA 憑證：**  
CloudFront 支援 256 位元金鑰。若要在 ACM 中使用 ECDSA 憑證，以便在檢視器和 CloudFront 之間請求使用 HTTPS，請使用 prime256v1 橢圓曲線。

## 支援的憑證類型
<a name="https-requirements-supported-types"></a>

CloudFront 支援由受信任憑證授權單位發行的所有憑證類型。

## 憑證過期日期和續約
<a name="https-requirements-cert-expiration"></a>

如果您使用從第三方憑證授權機構 (CA) 取得的憑證，則必須監控憑證過期日期，並在憑證過期之前續約您匯入至 AWS Certificate Manager (ACM) 或上傳至 AWS Identity and Access Management 憑證存放區的憑證。

**重要**  
為了避免憑證過期問題，請在目前憑證的 `NotAfter` 值之前至少 24 小時續約或重新匯入憑證。如果您的憑證在 24 小時內過期，請向 ACM 請求新憑證或將新憑證匯入 ACM。接著，將新憑證與 CloudFront 分佈建立關聯。  
當您的憑證續約或重新匯入正在進行時，CloudFront 可能會繼續使用先前的憑證。這是一個非同步程序，最多可能需要 24 小時的時間，CloudFront 才會顯示您的變更。

如果使用 ACM 提供的憑證，ACM 會為您管理憑證續約。如需詳細資訊，請參閱 *AWS Certificate Manager 使用者指南*中的[受管續約](https://docs.aws.amazon.com/acm/latest/userguide/managed-renewal.html)。

## CloudFront 分佈和憑證中的網域名稱
<a name="https-requirements-domain-names-in-cert"></a>

當您使用自訂原始伺服器時，原始伺服器上的 SSL/TLS 憑證包含 **Common Name** (通用名稱) 欄位中的網域名稱，且在 **Subject Alternative Names** (主體別名) 欄位中可能還有更多網域名稱。(CloudFront 在憑證網域名稱中支援萬用字元)。

憑證中其中一個網域名稱必須符合您指定給原始網域名稱的網域名稱。如果沒有相符的網域名稱，CloudFront 會將 HTTP 狀態碼 `502 (Bad Gateway)` 傳回到檢視器。

**重要**  
如果將替代網域名稱新增到分佈，CloudFront 會檢查替代網域名稱是否涵蓋在您所連線的憑證範圍內。憑證必須涵蓋憑證主體別名 (SAN) 欄位中的備用網域名稱。這表示 SAN 欄位必須包含完全相符的替代網域名稱，或在您要新增之替代網域名稱的相同層級包含萬用字元。  
如需詳細資訊，請參閱 [使用備用網域名稱的需求](CNAMEs.md#alternate-domain-names-requirements)。

## 最低 SSL/TLS 通訊協定版本
<a name="https-requirements-minimum-ssl-protocol-version"></a>

如果使用專用 IP 位址，請透過選擇安全政策來設定檢視器與 CloudFront 之間連線的最低 SSL/TLS 通訊協定版本。

如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [安全政策 (最低 SSL/TLS 版本)](DownloadDistValuesGeneral.md#DownloadDistValues-security-policy)。

## 支援的 HTTP 版本
<a name="https-requirements-supported-http-versions"></a>

如果您把一個憑證與多個 CloudFront 分發相關聯，則所有與憑證關聯的分發必須使用相同 [支援的 HTTP 版本](DownloadDistValuesGeneral.md#DownloadDistValuesSupportedHTTPVersions) 的選項。您在建立或更新 CloudFront 分佈時請指定此選項。

# 搭配 CloudFront 使用 SSL/TLS 憑證的配額 (僅限檢視器與 CloudFront 之間的 HTTPS)
<a name="cnames-and-https-limits"></a>

請注意以下將 SSL/TLS 憑證與 CloudFront 搭配使用的配額。這些配額僅適用於您使用匯入 ACM 的 AWS Certificate Manager (ACM) 佈建的 SSL/TLS 憑證，或上傳至 IAM 憑證存放區以在檢視器和 CloudFront 之間進行 HTTPS 通訊。

如需詳細資訊，請參閱[增加 SSL/TLS 憑證的配額](increasing-the-limit-for-ssl-tls-certificates.md)。

**每個 CloudFront 分佈的憑證數目上限**  
您可以把一個 SSL/TLS 憑證的上限數量與每個 CloudFront 分佈相關聯。

**您可以匯入 ACM 或上傳至 IAM 憑證存放區的憑證上限數量**  
如果您從第三方 CA 取得 SSL/TLS 憑證，您必須在以下其中一個位置存放憑證：  
+ **AWS Certificate Manager** – 如需 ACM 憑證數量的目前配額，請參閱 *AWS Certificate Manager 使用者指南*中的[配額](https://docs.aws.amazon.com/acm/latest/userguide/acm-limits.html)。列出的配額是包含您使用 ACM 佈建的憑證與匯入 ACM 的憑證之總和。
+ **IAM 憑證存放**區 – 如需您可以上傳到 AWS 帳戶 IAM 憑證存放區之憑證數量的目前配額 （先前稱為限制），請參閱《IAM **[使用者指南》中的 IAM 和 STS 限制](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html)。您可以在 Service Quotas 主控台請求提高配額。

**每個 AWS 帳戶的憑證數量上限 （僅限專用 IP 地址）**  
如果您想要使用專用 IP 位址提供 HTTPS 請求，請注意以下事項：  
+ 根據預設，CloudFront 會授予您在 AWS 帳戶中使用兩個憑證的許可，一個用於日常使用，另一個用於需要輪換多個分佈的憑證。
+ 如果您需要兩個以上的自訂 SSL/TLS 憑證 AWS ，您可以在 Service Quotas 主控台中請求更高的配額。

**將相同的憑證用於不同 AWS 帳戶建立的 CloudFront 分佈**  
如果您使用的是第三方 CA，而且想要搭配使用不同 AWS 帳戶建立的多個 CloudFront 分佈使用相同的憑證，您必須將憑證匯入 ACM，或為每個 AWS 帳戶將其上傳至 IAM 憑證存放區一次。  
如果您使用 ACM 提供的憑證，則不能配置 CloudFront 使用不同 AWS 帳戶建立的憑證。

**針對 CloudFront 和其他服務使用相同的憑證 AWS **  
如果您從信任的憑證授權機構購買憑證，例如 Comodo、DigiCert 或 Symantec，您可以將相同的憑證用於 CloudFront 和其他 AWS 服務。如果將憑證匯入到 ACM，則只需要匯入一次，即可將憑證用於多個 AWS 服務。  
如果您使用 ACM 提供的憑證，則在 ACM 中存放憑證。

**將相同的憑證用於多個 CloudFront 分佈**  
您可以對用來提供 HTTPS 請求的任何或所有 CloudFront 分佈使用相同的憑證。注意下列事項：  
+ 您可以使用相同的憑證提供使用專用 IP 位址的請求，與提供使用 SNI 的請求。
+ 您僅能把一個 SSL/TLS 憑證與每個 &CF; 分佈相關聯。
+ 每個分佈必須包含一或多個也出現在憑證中 **Common Name (通用名稱)** 欄位或 **Subject Alternative Names (主體別名)** 欄位的備用網域名稱。
+ 如果您使用專用 IP 位址提供 HTTPS 請求，且透過使用相同的 AWS 帳戶建立所有分佈，則可以藉由使用適用於所有分佈的相同憑證大幅降低您的成本。CloudFront 收取每個憑證的費用，而不是每個分佈。

  例如，假設您使用相同的 AWS 帳戶來建立三個分佈，並且針對所有三個分佈使用相同的憑證。您只需支付使用專用 IP 位址的費用一次。

  不過，如果您使用專用 IP 位址提供 HTTPS 請求，且在不同的 AWS 帳戶中使用相同的憑證建立 CloudFront 分佈，則需支付每個帳戶使用專用 IP 位址的費用。例如，如果您使用三個不同的 AWS 帳戶來建立三個分佈，並且針對所有三個分佈使用相同的憑證，則每個帳戶都會支付使用專用 IP 地址的完整費用。

# 設定備用網域名稱和 HTTPS
<a name="cnames-and-https-procedures"></a>

若要使用URL 中適用於檔案的備用網域名稱，與在檢視器和 CloudFront 之間使用 HTTPS，請執行適用的程序。

**Topics**
+ [取得 SSL/TLS 憑證](#cnames-and-https-getting-certificates)
+ [匯入 SSL/TLS 憑證](#cnames-and-https-uploading-certificates)
+ [更新您的 CloudFront 分佈](#cnames-and-https-updating-cloudfront)

## 取得 SSL/TLS 憑證
<a name="cnames-and-https-getting-certificates"></a>

如果您尚未擁有憑證，請取得一個 SSL/TLS 憑證。如需詳細資訊，請參閱適用的文件：
+ 若要使用 AWS Certificate Manager (ACM) 提供的憑證，請參閱 [AWS Certificate Manager 使用者指南](https://docs.aws.amazon.com/acm/latest/userguide/)。然後跳至 [更新您的 CloudFront 分佈](#cnames-and-https-updating-cloudfront)。
**注意**  
我們建議您使用 ACM 在 AWS 受管資源上佈建、管理和部署 SSL/TLS 憑證。您必須在美國東部 (維吉尼亞北部) 區域請求 ACM 憑證。
+ 若要從第三方憑證授權單位 (CA) 取得憑證，請參閱憑證授權單位提供的文件。當您有憑證時，請繼續進行下一個程序。

## 匯入 SSL/TLS 憑證
<a name="cnames-and-https-uploading-certificates"></a>

如果您從第三方 CA 取得憑證，請將憑證匯入到 ACM 或上傳至 IAM 憑證存放區：

**ACM (推薦)**  
ACM 讓您從 ACM 主控台以及透過程式設計方式匯入第三方憑證。如需將憑證匯入 ACM 的詳細資訊，請參閱 *AWS Certificate Manager 使用者指南*中的[將憑證匯入 AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/import-certificate.html)。您必須在美國東部 (維吉尼亞北部) 區域匯入憑證。

**IAM 憑證存放區**  
（不建議） 使用以下 AWS CLI 命令將您的第三方憑證上傳至 IAM 憑證存放區。  

```
aws iam upload-server-certificate \
        --server-certificate-name CertificateName \
        --certificate-body file://public_key_certificate_file \
        --private-key file://privatekey.pem \
        --certificate-chain file://certificate_chain_file \
        --path /cloudfront/path/
```
注意下列事項：  
+ **AWS 帳戶** – 您必須使用用來建立 CloudFront 分佈的相同 AWS 帳戶，將憑證上傳至 IAM 憑證存放區。
+ **--path 參數** – 當您將憑證上傳到 IAM 時，`--path` 參數 (憑證路徑) 的值必須以 `/cloudfront/` 開頭，例如 `/cloudfront/production/` 或 `/cloudfront/test/`。路徑必須以 / 結尾。
+ **現有的憑證** – 您必須指定 `--server-certificate-name` 和 `--path` 參數的值 (不同於與現有憑證相關聯的值)。
+ **使用 CloudFront 主控台** – 您在 中為 `--server-certificate-name` 參數指定的值 AWS CLI，例如 `myServerCertificate`，會出現在 CloudFront 主控台的 **SSL 憑證**清單中。
+ **使用 CloudFront API** – 請記下 AWS CLI 傳回的英數字元字串，例如 `AS1A2M3P4L5E67SIIXR3J`。這是您會在 `IAMCertificateId` 元素中指定的值。您不需要也由 CLI 傳回的 IAM ARN。
如需 的詳細資訊 AWS CLI，請參閱 [AWS Command Line Interface 使用者指南](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)和 [AWS CLI 命令參考](https://docs.aws.amazon.com/cli/latest/reference/)。

## 更新您的 CloudFront 分佈
<a name="cnames-and-https-updating-cloudfront"></a>

若要更新分佈的設定，請執行以下程序：<a name="cnames-and-https-updating-cloudfront-procedure"></a>

**設定適用於備用網域名稱的 CloudFront 分佈**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 選擇您希望更新的分佈 ID。

1. 在 **General (一般)** 索引標籤上，選擇 **Edit (編輯)**。

1. 更新下列的值：  
**備用網域名稱 (CNAME)**  
選擇**新增項目**，以新增適用的備用網域名稱。使用逗號區隔網域名稱，或在新的一行輸入每個網域名稱。  
**自訂 SSL 憑證**  
從下拉式清單中選取憑證。  
此處列出高達 100 個憑證。如果您有超過 100 個憑證，而您沒有看到想要新增的憑證，可以在欄位中輸入憑證 ARN 來選取。  
如果您將憑證上傳至 IAM 憑證存放區但它沒有被列出，而您無法在欄位中輸入名稱來選取，請檢閱此程序 [匯入 SSL/TLS 憑證](#cnames-and-https-uploading-certificates) 以確認您是否正確上傳憑證。  
在您把 SSL/TLS 憑證與 CloudFront 分佈相關聯後，請不要從 ACM 或 IAM 憑證存放區刪除憑證，直到您從所有分佈移除憑證且部署所有分佈。

1. 選擇**儲存變更**。

1. 將 CloudFront 設定為在檢視器和 CloudFront 之間請求使用 HTTPS：

   1. 在 **Behaviors (行為)** 索引標籤中，選擇您想要更新的快取行為，然後選擇 **Edit (編輯)**。

   1. 請針對 **Viewer Protocol Policy** (檢視器通訊協定政策) 指定下列其中一個值：  
**重新引導 HTTP 到 HTTPS**  
檢視器可以使用這兩種通訊協定，但會自動重新引導 HTTP 請求到 HTTPS 請求。CloudFront 會傳回 HTTP 狀態碼 `301 (Moved Permanently)` 以及新的 HTTPS URL。然後檢視器使用 HTTPS URL 重新將請求提交到 CloudFront。  
CloudFront 不會從 HTTP 將 `DELETE`、`OPTIONS`、`PATCH`、`POST` 或 `PUT` 請求重新引導到 HTTPS。如果將快取行為設定為重新引導至 HTTPS，則 CloudFront 會以 HTTP 狀態碼 `DELETE`，來回應此快取行為的 HTTP `OPTIONS`、`PATCH`、`POST`、`PUT` 或 `403 (Forbidden)` 請求。
當檢視器執行一個 HTTP 請求供其重新引導到 HTTPS 請求時，CloudFront 會收取這兩個請求的費用。針對 HTTP 請求，只會收取 CloudFront 傳回到檢視器的請求與標頭之費用。針對 HTTPS 請求，會收取該請求與標頭及原始伺服器傳回的檔案之費用。  
**僅限 HTTPS**  
檢視器只能在使用 HTTPS 的情況下存取您的內容。如果檢視器傳送 HTTP 請求，而不是 HTTPS 請求，則 CloudFront 會傳回 HTTP 狀態碼 `403 (Forbidden)`，且不會傳回檔案。

   1. 請選擇 **Yes, Edit (是，編輯)**。

   1. 為每個額外快取行為，供您要在檢視器與 CloudFront 之間使用 HTTPS，請重複執行步驟 a 到 c。

1. 您使用生產環境中已更新的組態之前，請先確認以下項目：
   + 每個快取行為中的路徑模式僅適用於您想要檢視器使用 HTTPS 的請求。
   + 以您想要 CloudFront 評估的順序列出快取行為。如需詳細資訊，請參閱 [路徑模式](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)。
   + 快取行為會將請求路由到正確的原始伺服器。

# 判斷 SSL/TLS RSA 憑證中公有金鑰的大小
<a name="cnames-and-https-size-of-public-key"></a>

如果使用 CloudFront 備用網域名稱和 HTTPS，SSL/TLS RSA 憑證中的公有金鑰大小上限為 4096 位元。(這是金鑰大小，而不是公有金鑰中字元的數量)。如果您使用 AWS Certificate Manager 做為憑證，雖然 ACM 支援較大的 RSA 金鑰，但無法搭配 CloudFront 使用較大的金鑰。

您可以透過執行以下 OpenSSL 命令判斷 RSA 公有金鑰的大小：

```
openssl x509 -in path and filename of SSL/TLS certificate -text -noout 
```

其中：
+ `-in` 會指定 SSL/TLS RSA 憑證的路徑和檔案名稱。
+ `-text` 會讓 OpenSSL 以位元為單位顯示 RSA 公有金鑰的長度。
+ `-noout` 避免 OpenSSL 顯示公有金鑰。

輸出範例：

```
Public-Key: (2048 bit)
```

# 增加 SSL/TLS 憑證的配額
<a name="increasing-the-limit-for-ssl-tls-certificates"></a>

您可以匯入 AWS Certificate Manager (ACM) 或上傳到 AWS Identity and Access Management (IAM) 的 SSL/TLS 憑證數量有配額。當您將 CloudFront 設定為使用專用 IP 地址來提供 HTTPS 請求 AWS 帳戶 時，您可以搭配 使用的 SSL/TLS 憑證數量也有配額。不過，您可以請求提高配額。

**Topics**
+ [增加匯入 ACM 的憑證配額](#certificates-to-import-into-acm)
+ [增加上傳到 IAM 的憑證配額](#certificates-to-upload-into-iam)
+ [增加與專用 IP 位址搭配使用的憑證配額](#certificates-using-dedicated-ip-address)

## 增加匯入 ACM 的憑證配額
<a name="certificates-to-import-into-acm"></a>

如需可匯入 ACM 之憑證數量的配額，請參閱 *AWS Certificate Manager 使用者指南*中的[配額](https://docs.aws.amazon.com/acm/latest/userguide/acm-limits.html)。

若要請求提升配額，您可以使用 Service Quotas 主控台。如需詳細資訊，請參閱「Service Quotas 使用者指南」**中的[請求提高配額](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。

## 增加上傳到 IAM 的憑證配額
<a name="certificates-to-upload-into-iam"></a>

如需您可以上傳到 IAM 的憑證數量配額 (先前稱為限制)，請參閱 *IAM 使用者指南*中的 [IAM 和 STS 限制](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html)。

若要請求提升配額，您可以使用 Service Quotas 主控台。如需詳細資訊，請參閱「Service Quotas 使用者指南」**中的[請求提高配額](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。

## 增加與專用 IP 位址搭配使用的憑證配額
<a name="certificates-using-dedicated-ip-address"></a>

如需使用專用 IP 地址提供 HTTPS 請求 AWS 帳戶 時，每個憑證可使用的 SSL 憑證數量配額，請參閱 [SSL 憑證的配額](cloudfront-limits.md#limits-ssl-certificates)。

若要請求提升配額，您可以使用 Service Quotas 主控台。如需詳細資訊，請參閱「Service Quotas 使用者指南」**中的[請求提高配額](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。

# 輪換 SSL/TLS 憑證
<a name="cnames-and-https-rotate-certificates"></a>

當您的 SSL/TLS 憑證即將過期時，您需要輪換憑證以確保分佈的安全性，並避免檢視器的服務中斷。您可用下列方式輪換憑證：
+ 對於 AWS Certificate Manager (ACM) 提供的 SSL/TLS 憑證，您不需要輪換它們。ACM 會*自動*為您管理憑證續約。如需詳細資訊，請參閱《*AWS Certificate Manager 使用者指南*》中的「[受管憑證續約](https://docs.aws.amazon.com/acm/latest/userguide/acm-renewal.html)」。
+ 如果您使用第三方憑證認證機構，而且已將憑證匯入 ACM (建議) 或上傳到 IAM 憑證存放區，則必須偶爾使用另一個憑證來替換某個憑證。

  

**重要**  
ACM 不會為您從第三方憑證認證機構取得並匯入到 ACM 的憑證管理憑證續約。
如果您設定 CloudFront 使用專用 IP 位址提供 HTTPS 請求，在更換憑證時，則可能需要支付額外按比例計算的費用來使用一或多個額外的憑證。我們建議您更新分佈，把額外的費用降到最低。

## 輪換 SSL/TLS 憑證
<a name="rotate-ssl-tls-certificate"></a>

若要輪換憑證，請執行以下程序。在您更換憑證的同時以及處理完成後，檢視器皆能持續存取您的內容。<a name="rotate-ssl-tls-certificates-proc"></a>

**若要輪換 SSL/TLS 憑證**

1. [增加 SSL/TLS 憑證的配額](increasing-the-limit-for-ssl-tls-certificates.md) 判斷您是否需要使用更多 SSL 憑證的許可。若是如此，請請求許可並等到授予許可時，再繼續步驟 2。

1. 將新憑證匯入到 ACM 或上傳至 IAM。如需詳細資訊，請參閱 *Amazon CloudFront 開發人員指南*中的[匯入 SSL/TLS 憑證](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-procedures.html#cnames-and-https-uploading-certificates)。

1. (僅限 IAM 憑證) 一次更新一個分佈，以使用新的憑證。如需詳細資訊，請參閱[更新分佈](HowToUpdateDistribution.md)。

1. (選用) 從 ACM 或 IAM 刪除先前的憑證。
**重要**  
請勿刪除 SSL/TLS 憑證，直到您將其從所有分佈中移除，並直到您已更新的分佈已變更為 `Deployed`。

# 從自訂 SSL/TLS 憑證還原到預設 CloudFront 憑證
<a name="cnames-and-https-revert-to-cf-certificate"></a>

如果您已將 CloudFront 設定為在檢視器和 CloudFront 之間使用 HTTPS，且已將 CloudFront 設定為使用自訂 SSL/TLS 憑證，則可以變更設定以使用預設 CloudFront SSL/TLS 憑證。此程序取決於您是否已使用分佈來分配您的內容：
+ 如果您尚未使用分佈來分配內容，可以只變更組態。如需詳細資訊，請參閱 [更新分佈](HowToUpdateDistribution.md)。
+ 如果您已經使用分佈來分配內容，則您必須建立新的 CloudFront 分配和變更檔案的 URL，以降低或消除內容不可用的時間。若要執行此操作，請執行以下程序。

## 還原為預設 CloudFront 憑證
<a name="revert-default-cloudfront-certificate"></a>

以下程序顯示如何從自訂 SSL/TLS 憑證還為到預設 CloudFront 憑證。<a name="cnames-and-https-revert-to-cf-certificate-proc"></a>

**還原為預設 CloudFront 憑證**

1. 使用所需的組態建立新的 CloudFront 分佈。針對 **SSL 憑證**，選擇 **預設 CloudFront 憑證 (\$1.cloudfront.net)**。

   如需詳細資訊，請參閱[建立分發](distribution-web-creating-console.md)。

1. 針對您使用 CloudFront 所分佈的檔案，請更新應用程式中的 URL，以使用 CloudFront 指派給新分佈的網域名稱。例如，請將 `https://www.example.com/images/logo.png` 變更為 `https://d111111abcdef8.cloudfront.net/images/logo.png`。

1. 刪除與自訂 SSL/TLS 憑證相關聯的分佈，或是更新分佈，將 **SSL 憑證**的值變更為**預設 CloudFront 憑證 (\$1.cloudfront.net)**。如需詳細資訊，請參閱[更新分佈](HowToUpdateDistribution.md)。
**重要**  
在您完成此步驟之前， AWS 會繼續向您收取使用自訂 SSL/TLS 憑證的費用。

1. (選用) 刪除您的自訂 SSL/TLS 憑證。

   1. 執行 AWS CLI 命令`list-server-certificates`以取得您要刪除之憑證的憑證 ID。如需詳細資訊，請參閱 *AWS CLI 命令參考*中的 [list-server-certificates](https://docs.aws.amazon.com/cli/latest/reference/iam/list-server-certificates.html)。

   1. 執行 AWS CLI 命令`delete-server-certificate`來刪除憑證。如需詳細資訊，請參閱 *AWS CLI 命令參考*中的 [delete-server-certificate](https://docs.aws.amazon.com/cli/latest/reference/iam/delete-server-certificate.html)。

# 若要從具有專用 IP 位址的自訂 SSL/TLS 憑證切換到 SNI
<a name="cnames-and-https-switch-dedicated-to-sni"></a>

如果您設定 CloudFront 使用有專用 IP 位址的自訂 SSL/TLS 憑證，您可以切換為使用有 SNI 的自訂 SSL/TLS 憑證，並消除與專用 IP 位址關聯的費用。

**重要**  
對 CloudFront 組態的此更新對支援 SNI 的檢視器沒有任何影響。檢視器可以在變更之前和之後存取您的內容，也可以在變更傳播到 CloudFront 節點位置時存取內容。不支援 SNI 的檢視器在變更之後不能存取您的內容。如需詳細資訊，請參閱[選擇 CloudFront 提供 HTTPS 請求的方式](cnames-https-dedicated-ip-or-sni.md)。

## 從自訂憑證切換至 SNI
<a name="cloudfront-switch-custom-cert-sni"></a>

下列程序顯示如何從具有專用 IP 位址的自訂 SSL/TLS 憑證切換到 SNI。<a name="cnames-and-https-switch-dedicated-to-sni-proc"></a>

**若要從具有專用 IP 位址的自訂 SSL/TLS 憑證切換到 SNI**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 選擇欲檢閱或更新的分佈 ID。

1. 請選擇 **Distribution Settings (分佈設定)**。

1. 在 **General (一般)** 索引標籤上，選擇 **Edit (編輯)**。

1. 在**自訂 SSL 憑證 – *選用***下，取消選取**舊版用戶端支援**。

1. 請選擇 **Yes, Edit (是，編輯)**。

# 使用 CloudFront 進行相互 TLS 身分驗證 （檢視器 mTLS)
<a name="mtls-authentication"></a>

相互 TLS 身分驗證 （相互傳輸層安全身分驗證 — mTLS) 是一種安全通訊協定，透過要求雙向憑證型身分驗證來延伸標準 TLS 身分驗證，其中用戶端和伺服器都必須證明其身分，才能建立安全連線。使用交互 TLS，您可以確保只有提供信任 TLS 憑證的用戶端才能存取您的 CloudFront 分佈。

## 運作方式
<a name="how-mtls-works"></a>

在標準 TLS 交握中，只有伺服器會呈現憑證，向用戶端證明其身分。使用交互 TLS，身分驗證程序會變成雙向。當用戶端嘗試連線至 CloudFront 分佈時，CloudFront 會在 TLS 交握期間請求用戶端憑證。在建立安全連線之前，用戶端必須呈現 CloudFront 針對您設定的信任存放區驗證的有效 X.509 憑證。

CloudFront 會在 AWS 節點執行此憑證驗證，從原始伺服器卸載身分驗證複雜性，同時維護 CloudFront 的全域效能優勢。您可以將 mTLS 設定為兩種模式：驗證模式 （需要所有用戶端呈現有效的憑證） 或選用模式 （在呈現時驗證憑證，但也允許沒有憑證的連線）。

## 使用案例
<a name="mtls-use-cases"></a>

使用 CloudFront 的相互 TLS 身分驗證可解決傳統身分驗證方法不足的幾個關鍵安全案例：
+ **裝置身分驗證與內容快取** - 您可以在允許存取韌體更新、遊戲下載或內部資源之前，對遊戲主控台、IoT 裝置或公司硬體進行身分驗證。每個裝置都包含唯一憑證，可證明其真實性，同時受益於 CloudFront 的快取功能。
+ **API-to-API 身分驗證** - 您可以保護信任的業務合作夥伴、付款系統或微型服務之間的machine-to-machine通訊。憑證型身分驗證不需要共用秘密或 API 金鑰，同時為自動化資料交換提供強大的身分驗證。

**Topics**
+ [運作方式](#how-mtls-works)
+ [使用案例](#mtls-use-cases)
+ [信任存放區和憑證管理](trust-stores-certificate-management.md)
+ [為 CloudFront 分佈啟用交互 TLS](enable-mtls-distributions.md)
+ [關聯 CloudFront 連線函數](connection-functions.md)
+ [設定其他設定](configuring-additional-settings.md)
+ [快取政策並轉送至原始伺服器的檢視器 mTLS 標頭](viewer-mtls-headers.md)
+ [使用 CloudFront Connection Function 和 KVS 撤銷](revocation-connection-function-kvs.md)
+ [使用連線日誌的可觀測性](connection-logs.md)

# 信任存放區和憑證管理
<a name="trust-stores-certificate-management"></a>

建立和設定信任存放區是使用 CloudFront 實作交互 TLS 身分驗證的必要要求。信任存放區包含 CloudFront 在身分驗證程序期間用來驗證用戶端憑證的憑證授權機構 (CA) 憑證。

## 什麼是信任存放區？
<a name="what-is-trust-store"></a>

信任存放區是 CA 憑證的儲存庫，CloudFront 會使用此儲存庫在交互 TLS 身分驗證期間驗證用戶端憑證。信任存放區包含根 CA 憑證和中繼 CA 憑證，這些憑證構成用於驗證用戶端憑證的信任鏈。

當您使用 CloudFront 實作交互 TLS 時，信任存放區會定義您信任哪些憑證授權機構來發行有效的用戶端憑證。CloudFront 會在 TLS 交握期間，針對您的信任存放區驗證每個用戶端憑證。只有呈現連結至信任存放區中其中一個 CAs 的憑證的用戶端才會成功驗證。

CloudFront 中的信任存放區是可與多個分佈建立關聯的帳戶層級資源。這可讓您在整個 CloudFront 部署中維持一致的憑證驗證政策，同時簡化 CA 憑證管理。

## 憑證授權單位支援
<a name="ca-support"></a>

CloudFront 支援 AWS 私有憑證授權單位和第三方私有憑證授權單位發行的憑證。此彈性可讓您根據您的組織需求，使用現有的憑證基礎設施或利用 AWS 受管憑證服務。
+ **AWS 私有憑證授權機構：**您可以使用 AWS Private CA 發行的憑證，該憑證提供受管私有憑證授權機構服務。此整合可簡化憑證生命週期管理，並提供與其他 AWS 服務的無縫整合。
+ **第三方私有憑證授權機構：**您也可以使用現有私有憑證授權機構基礎設施的憑證，包括企業 CAs 或其他第三方憑證提供者。這可讓您維護目前的憑證管理程序，同時新增 CloudFront 的 mTLS 功能。

## 憑證需求和規格
<a name="certificate-requirements"></a>

信任存放區對其包含的 CA 憑證有特定要求：

### CA 憑證格式要求
<a name="ca-cert-format-requirements"></a>
+ **格式：**PEM （隱私權增強郵件） 格式
+ **內容界限：**憑證必須括在 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 邊界內
+ **註解：**必須以 \$1 字元開頭，且不能包含任何 - 字元
+ **換行：**憑證之間不允許空白行

### 支援的憑證規格
<a name="supported-cert-specs"></a>
+ **憑證類型：**X.509v3
+ **公有金鑰類型：**
  + RSA 2048、RSA 3072、RSA 4096
  + ECDSA：secp256r1、secp384r1
+ **簽章演算法：**
  + SHA256, SHA384, SHA512搭配 RSA
  + SHA256, SHA384, SHA512搭配 EC
  + SHA256, SHA384, SHA512搭配 RSASSA-PSS 搭配 MGF1

### 憑證套件格式範例
<a name="example-cert-bundle"></a>

多個憑證 (PEM 編碼）：

```
# Root CA Certificate
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvD/XqiMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwNzEyMTU0NzQ4WhcNMjcwNzEwMTU0NzQ4WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExKvY1xzHFylsHiuowqpmzs7rEcuuylOuEszpFp+BtXh0ZuEtts9LP
-----END CERTIFICATE-----
# Intermediate CA Certificate
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvD/XqjMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwNzEyMTU0NzQ4WhcNMjcwNzEwMTU0NzQ4WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExKvY1xzHFylsHiuowqpmzs7rEcuuylOuEszpFp+BtXh0ZuEtts9LP
-----END CERTIFICATE-----
```

## 建立信任存放區
<a name="create-trust-store"></a>

建立信任存放區之前，您必須將 PEM 格式的 CA 憑證套件上傳至 Amazon S3 儲存貯體。憑證套件應包含驗證用戶端憑證所需的所有信任根憑證和中繼 CA 憑證。

建立信任存放區時，CA 憑證套件只會從 S3 讀取一次。如果未來變更 CA 憑證套件，則必須手動更新信任存放區。信任存放區和 S3 CA 憑證套件之間不會保留同步。

### 先決條件
<a name="trust-store-prerequisites"></a>
+ 從您的憑證授權機構 (CA) 上傳到 Amazon S3 儲存貯體的憑證套件
+ 建立 CloudFront 資源的必要許可

### 建立信任存放區 （主控台）
<a name="create-trust-store-console"></a>

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**信任存放**區。

1. 選擇**建立信任存放區**。

1. 針對**信任存放區名稱**，輸入信任存放區的名稱。

1. 針對**憑證授權機構 (CA) 套件**，輸入 PEM 格式 CA 憑證套件的 Amazon S3 路徑。

1. 選擇**建立信任存放區**。

### 建立信任存放區 (AWS CLI)
<a name="create-trust-store-cli"></a>

```
aws cloudfront create-trust-store \
  --name MyTrustStore \
  --ca-certificates-bundle-source '{"CaCertificatesBundleS3Location":{"Bucket":"my-bucket","Key":"ca-bundle.pem","Region":"bucket-region"}}' \
  --tags Items=[{Key=Environment,Value=Production}]
```

## 將信任存放區與分佈建立關聯
<a name="associate-trust-store"></a>

建立信任存放區之後，您必須將其與 CloudFront 分佈建立關聯，才能啟用交互 TLS 身分驗證。

### 先決條件
<a name="associate-prerequisites"></a>
+ 已啟用僅 HTTPS 檢視器通訊協定政策且 HTTP3 支援已停用的現有 CloudFront 分佈。

### 建立信任存放區的關聯 （主控台）
<a name="associate-trust-store-console"></a>

CloudFront 主控台中的信任存放區有兩種關聯方式：透過信任存放區詳細資訊頁面或透過分佈設定頁面。

**透過信任存放區詳細資訊頁面關聯信任存放區：**

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**信任存放**區。

1. 選擇您要關聯的信任存放區名稱。

1. 選擇**關聯以分佈**。

1. 設定可用的檢視器 mTLS 選項：
   + **用戶端憑證驗證模式：**選擇必要和選用模式。在必要模式下，所有用戶端都需要呈現憑證。在選用模式中，會驗證呈現憑證的用戶端，而未呈現憑證的用戶端則允許存取。
   + **公告信任存放區 CA 名稱：**選擇是否要在 TLS 交握期間將信任存放區中的 CA 名稱公告給用戶端。
   + **忽略憑證過期日期：**選擇是否允許憑證過期的連線 （其他驗證條件仍適用）。
   + **連線函數：**選用的連線函數可以建立關聯，以根據其他自訂條件允許/拒絕連線。

1. 選取要與信任存放區建立關聯的一或多個分佈。只有停用 HTTP3 且具有僅限 HTTPS 快取行為的分佈，才能支援檢視器 mTLS。

1. 選擇**關聯**。

**透過分佈設定頁面關聯信任存放區：**

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 選取您要關聯的分佈

1. 在**一般**索引標籤下方的**設定**容器中，選擇右上角的**編輯** 

1. 向下捲動至頁面底部，在**連線**容器中切換**檢視器 mTLS** 開啟

1. 設定可用的檢視器 mTLS 選項：
   + **用戶端憑證驗證模式：**選擇必要和選用模式。在必要模式下，所有用戶端都需要呈現憑證。在選用模式中，會驗證呈現憑證的用戶端，而未呈現憑證的用戶端則允許存取。
   + **公告信任存放區 CA 名稱：**選擇是否要在 TLS 交握期間將信任存放區中的 CA 名稱公告給用戶端。
   + **忽略憑證過期日期：**選擇是否允許憑證過期的連線 （其他驗證條件仍適用）。
   + **連線函數：**選用的連線函數可以建立關聯，以根據其他自訂條件允許/拒絕連線。

1. 選擇右下角的**儲存變更**。

### 建立信任存放區 (AWS CLI) 的關聯
<a name="associate-trust-store-cli"></a>

信任存放區可以透過 DistributionConfig.ViewerMtlsConfig 屬性與分佈建立關聯。這表示我們首先需要擷取分佈組態，然後在後續的 UpdateDistribution 請求中提供 ViewerMtlsConfig。

```
// First fetch the distribution
aws cloudfront get-distribution {DISTRIBUTION_ID}

// Update the distribution config, for example:
Distribution config, file://distConf.json: 
{
  ...other fields,
  ViewerMtlsConfig: {
    Mode: 'required',
    TrustStoreConfig: {
        AdvertiseTrustStoreCaNames: false,
        IgnoreCertificateExpiry: true,
        TrustStoreId: {TRUST_STORE_ID}
    }
  }
}

aws cloudfront update-distribution \
   --id {DISTRIBUTION_ID} \
   --if-match {ETAG} \
   --distribution-config file://distConf.json
```

## 管理信任存放區
<a name="manage-trust-stores"></a>

### 檢視信任存放區詳細資訊
<a name="view-trust-store-details"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**信任存放**區。

1. 選擇信任存放區的名稱以檢視其詳細資訊頁面。

詳細資訊頁面顯示：
+ 信任存放區名稱和 ID
+ CA 憑證數量
+ 建立日期和上次修改日期
+ 關聯的分佈
+ Tags (標籤)

### 修改信任存放區
<a name="modify-trust-store"></a>

若要取代 CA 憑證套件：

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**信任存放**區。

1. 選擇信任存放區的名稱。

1. 選擇**動作**，然後選擇**編輯**。

1. 針對**憑證授權單位 (CA) 套件**，輸入更新後的 CA 套件 PEM 檔案的 Amazon S3 位置。

1. 選擇**更新信任存放區**。

### 刪除信任存放區
<a name="delete-trust-store"></a>

**先決條件：**您必須先取消信任存放區與所有 CloudFront 分佈的關聯。

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**信任存放**區。

1. 選擇信任存放區的名稱。

1. 選擇**刪除信任存放區**。

1. 選擇**刪除**以確認刪除。

### 後續步驟
<a name="trust-store-next-steps"></a>

在建立信任存放區並將其與 CloudFront 分發建立關聯之後，您可以繼續在分發上啟用交互 TLS 身分驗證，並設定其他設定，例如將憑證標頭轉送至原始伺服器。如需在 分佈上啟用 mTLS 的詳細說明，請參閱 [為 CloudFront 分佈啟用交互 TLS](enable-mtls-distributions.md)。

# 為 CloudFront 分佈啟用交互 TLS
<a name="enable-mtls-distributions"></a>

## 先決條件和要求
<a name="mtls-prerequisites-requirements"></a>

CloudFront 的交互 TLS 驗證模式要求所有用戶端在 TLS 交握期間呈現有效的憑證，並拒絕沒有有效憑證的連線。在 CloudFront 分佈上啟用交互 TLS 之前，請確定您有：
+ 使用憑證授權單位憑證建立信任存放區
+ 將信任存放區與您的 CloudFront 分佈建立關聯
+ 確保所有分佈快取行為都使用僅限 HTTPS 的檢視器通訊協定政策
+ 確保您的分佈使用 HTTP/2 （預設設定，HTTP/3 不支援檢視器 mTLS)

**注意**  
相互 TLS 身分驗證需要檢視器和 CloudFront 之間的 HTTPS 連線。您無法在具有支援 HTTP 連線之任何快取行為的分佈上啟用 mTLS。

## 啟用交互 TLS （主控台）
<a name="enable-mtls-console"></a>

### 對於新分佈
<a name="enable-mtls-new-distributions"></a>

在 CloudFront 主控台中建立新分佈的過程中，無法設定檢視器 mTLS。首先透過任何方式 （主控台、CLI、API) 建立分佈，然後編輯分佈設定，以根據下列現有的分佈說明啟用檢視器 mTLS。

### 對於現有的分佈
<a name="enable-mtls-existing-distributions"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 從分佈清單中，選取您要修改的分佈。

1. 確定針對所有快取行為，檢視器通訊協定政策設定為將 **HTTP 重新導向至 HTTPS** 或**僅限 HTTPS**。（您可以選擇**快取行為**索引標籤，以使用 HTTP 通訊協定政策檢視和更新任何快取行為。)

1. 選擇**一般**索引標籤。

1. 在 **Settings** (設定) 區段中，選擇 **Edit** (編輯)。

1. 在**連線**區段中，尋找**檢視器交互身分驗證 (mTLS)**。

1. 將**啟用交互身分驗證**切換為開啟。

1. 對於**用戶端憑證驗證模式**，選取**必要** （所有用戶端都必須顯示憑證） 或**選用** （用戶端可以選擇性顯示憑證）。

1. 針對**信任存放區**，選取您先前建立的信任存放區。

1. （選用） 如果您希望 CloudFront 在 TLS 交握期間將 **CA 名稱傳送給用戶端，請切換公告信任存放**區 CA 名稱。

1. （選用） 如果您想要允許憑證過期的連線，請切換**忽略憑證過期日期**。

1. 選擇**儲存變更**。

## 啟用交互 TLS (AWS CLI)
<a name="enable-mtls-cli"></a>

### 對於新分佈
<a name="enable-mtls-cli-new"></a>

下列範例示範如何建立包含 mTLS 設定的分佈組態檔案 (distribution-config.json)：

```
{
  "CallerReference": "cli-example-1",
  "Origins": {
    "Quantity": 1,
    "Items": [
      {
        "Id": "my-origin",
        "DomainName": "example.com",
        "CustomOriginConfig": {
          "HTTPPort": 80,
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only"
        }
      }
    ]
  },
  "DefaultCacheBehavior": {
    "TargetOriginId": "my-origin",
    "ViewerProtocolPolicy": "https-only",
    "MinTTL": 0,
    "ForwardedValues": {
      "QueryString": false,
      "Cookies": {
        "Forward": "none"
      }
    }
  },
  "ViewerCertificate": {
    "CloudFrontDefaultCertificate": true
  },
  "ViewerMtlsConfig": {
    "Mode": "required", 
    "TrustStoreConfig": {
        "TrustStoreId": {TRUST_STORE_ID},
        "AdvertiseTrustStoreCaNames": true,
        "IgnoreCertificateExpiry": true
    }
  },
  "Enabled": true
}
```

使用下列範例命令建立已啟用 mTLS 的分佈：

```
aws cloudfront create-distribution --distribution-config file://distribution-config.json
```

### 對於現有的分佈
<a name="enable-mtls-cli-existing"></a>

使用下列範例命令取得目前的分佈組態：

```
aws cloudfront get-distribution-config --id E1A2B3C4D5E6F7 --output json > dist-config.json
```

編輯 檔案以新增 mTLS 設定。將下列範例區段新增至您的分佈組態：

```
"ViewerMtlsConfig": {
    "Mode": "required", 
    "TrustStoreConfig": {
        "TrustStoreId": {TRUST_STORE_ID},
        "AdvertiseTrustStoreCaNames": true,
        "IgnoreCertificateExpiry": true
    }
}
```

從檔案移除 ETag 欄位，但分別儲存其值。

使用下列範例命令，使用新組態更新分佈：

```
aws cloudfront update-distribution \
    --id E1A2B3C4D5E6F7 \
    --if-match YOUR-ETAG-VALUE \
    --distribution-config file://dist-config.json
```

## 檢視器通訊協定政策
<a name="viewer-protocol-policies"></a>

使用交互 TLS 時，所有分佈快取行為都必須使用僅限 HTTPS 的檢視器通訊協定政策進行設定：
+ 將 **HTTP 重新導向至 HTTPS** - 在執行憑證驗證之前將 HTTP 請求重新導向至 HTTPS。
+ **僅限 HTTPS** - 僅接受 HTTPS 請求並執行憑證驗證。

**注意**  
交互 TLS 不支援 HTTP 和 HTTPS 檢視器通訊協定政策，因為 HTTP 連線無法執行憑證驗證。

## 後續步驟
<a name="enable-mtls-next-steps"></a>

在 CloudFront 分佈上啟用檢視器 TLS 之後，您可以關聯連線函數來實作自訂憑證驗證邏輯。Connection Functions 可讓您使用自訂驗證規則、憑證撤銷檢查和記錄來擴展內建 mTLS 身分驗證功能。如需建立和關聯連線函數的詳細資訊，請參閱 [關聯 CloudFront 連線函數](connection-functions.md)。

# 關聯 CloudFront 連線函數
<a name="connection-functions"></a>

CloudFront Connection Functions 可讓您在 TLS 交握期間實作自訂憑證驗證邏輯，提供內建 mTLS 身分驗證功能的延伸。

## 什麼是連線函數？
<a name="what-are-connection-functions"></a>

連線函數是在用戶端憑證經過驗證後，在 TLS 交握期間執行的 JavaScript 函數。已驗證的用戶端憑證會傳遞至 Connection Function，連線函數可以在此時對是否授予存取權進行額外判斷。如需連線函數的詳細資訊，請參閱 [使用 CloudFront Functions 在邊緣進行自訂](cloudfront-functions.md)。

## Connection Functions 如何使用 mTLS
<a name="how-connection-functions-work"></a>

當用戶端嘗試建立與 CloudFront 分佈的 mTLS 連線時，會發生下列順序：

1. 用戶端使用 CloudFront 節點啟動 TLS 交握。

1. CloudFront 請求和接收用戶端憑證。

1. CloudFront 會對信任存放區執行標準憑證驗證。

1. 如果憑證通過標準驗證，CloudFront 會叫用您的連線函數。如果在 **ViewerMtlsConfig** 中啟用了 **IgnoreCertificateExpiry**，則您的過期但有效憑證也會傳遞至連線函數。如果用戶端憑證無效，將不會叫用連線函數。

1. 您的 Connection Function 會收到剖析的憑證資訊和連線詳細資訊。

1. 您的函數會根據自訂邏輯做出允許/拒絕決策。

1. CloudFront 會根據您的決定完成或終止 TLS 連線。

驗證模式和選用模式 （當用戶端呈現憑證時） 都會叫用連線函數。

## 建立連線函數
<a name="create-connection-function"></a>

您可以使用 CloudFront 主控台或 CLI AWS 建立連線函數。

### 建立連線函數 （主控台）
<a name="create-connection-function-console"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽視窗中，選擇**函數**。

1. 選擇**連線函數**索引標籤，然後選擇**建立連線函數**。

1. 輸入您 AWS 帳戶中唯一的函數名稱。

1. 選擇**繼續**。

1. 在函數編輯器中，撰寫要驗證憑證的 JavaScript 程式碼。函數處理常式必須呼叫允許或拒絕。

1. 選用：KeyValue 存放區可以與 Connection Function 建立關聯，以實作撤銷控制。

1. 選擇**儲存變更**。

### 建立連線函數 (AWS CLI)
<a name="create-connection-function-cli"></a>

下列範例示範如何建立連線函數：

將函數程式碼寫入不同的檔案中，例如 code.js：

```
function connectionHandler(connection) {
  connection.allow();
}
```

```
aws cloudfront create-connection-function \
  --name "certificate-validator" \
  --connection-function-config '{
      "Comment": "Client certificate validation function",
      "Runtime": "cloudfront-js-2.0"
  }' \
  --connection-function-code fileb://code.js
```

## Connection Function 程式碼結構
<a name="connection-function-code-structure"></a>

Connection Functions 實作 connectionHandler 函數，該函數會接收包含憑證和連線資訊的連線物件。您的函數必須使用 `connection.allow()`或 `connection.deny()`來決定連線。

### 基本連線函數範例
<a name="basic-connection-function-example"></a>

下列範例顯示簡單的連線函數，可驗證用戶端憑證的主旨欄位：

```
function connectionHandler(connection) {
    // Only process if a certificate was presented
    if (!connection.clientCertificate) {
        console.log("No certificate presented");
        connection.deny();
    }
    
    // Check the subject field for specific organization
    const subject = connection.clientCertificate.certificates.leaf.subject;
    if (!subject.includes("O=ExampleCorp")) {
        console.log("Certificate not from authorized organization");
       connection.deny();
    } else {
        // All checks passed
        console.log("Certificate validation passed");
        connection.allow();
    }
}
```

連線物件上可用的用戶端憑證屬性完整規格可在此處取得：

```
{
  "connectionId": "Fdb-Eb7L9gVn2cFakz7wWyBJIDAD4-oNO6g8r3vXDV132BtnIVtqDA==", // Unique identifier for this TLS connection
  "clientIp": "203.0.113.42", // IP address of the connecting client (IPv4 or IPv6)
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "subject": "CN=client.example.com,O=Example Corp,C=US", // Distinguished Name (DN) of the certificate holder
        "issuer": "CN=Example Corp Intermediate CA,O=Example Corp,C=US", // Distinguished Name (DN) of the certificate authority that issued this certificate
        "serialNumber": "4a:3f:5c:92:d1:e8:7b:6c", // Unique serial number assigned by the issuing CA (hexadecimal)
        "validity": {
          "notBefore": "2024-01-15T00:00:00Z", // Certificate validity start date (ISO 8601 format)
          "notAfter": "2025-01-14T23:59:59Z"   // Certificate expiration date (ISO 8601 format)
        },
        "sha256Fingerprint": "a1b2c3d4e5f6...abc123def456", // SHA-256 hash of the certificate (64 hex characters)
      },
    },
  },
}
```

## 關聯連線函數
<a name="associate-connection-function-section"></a>

建立連線函數之後，您必須將其發佈至 LIVE 階段，並將其與您的分佈建立關聯。

### 發佈和關聯連線函數 （主控台）
<a name="publish-associate-console"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**函數**

1. 選擇**連線函數**索引標籤，然後選取您的連線函數。

1. 選擇**發佈**以將其移至 LIVE 階段。

1. 在發佈區段下方的關聯分佈表格中，選擇**新增關聯**。

1. 選取已啟用檢視器 mTLS 的分佈，以便與之建立關聯。

或者，也可以從分佈詳細資訊頁面關聯已發佈的連線函數。

1. 導覽至列出所有分發的主控台首頁。

1. 選取您要關聯的分佈。

1. 選擇**一般**索引標籤。

1. 在 **Settings** (設定) 區段中，選擇 **Edit** (編輯)。

1. 在**連線**區段中，尋找**檢視器交互身分驗證 (mTLS)**。

1. 針對**連線函數**，選取您的函數。

1. 選擇**儲存變更**。

### 建立連線函數 (AWS CLI) 的關聯
<a name="associate-connection-function-cli"></a>

下列範例示範如何將 Connection Function 與分佈建立關聯：

```
// DistributionConfig:
{
   ...other settings,
    "ConnectionFunctionAssociation": {
        "Id": "cf_30c2CV2elHwCoInb3LtcaUJkZeD"
    }
}
```

## Connection Functions 的使用案例
<a name="connection-function-use-cases"></a>

Connection Functions 啟用數個進階 mTLS 使用案例：
+ **憑證屬性驗證** - 驗證用戶端憑證中的特定欄位，例如組織單位要求或主體替代名稱模式。
+ **憑證撤銷檢查** - 使用 KeyValueStore 實作自訂憑證撤銷檢查，以存放已撤銷的憑證序號。
+ **以 IP 為基礎的憑證政策** - 根據用戶端 IP 地址或地理限制套用不同的憑證政策。
+ **多租戶驗證** - 實作租戶特定的驗證規則，其中根據主機名稱或憑證屬性套用不同的憑證要求。

**注意**  
在 TLS 交握期間，連線函數每個用戶端連線執行一次。  
Connection Functions 只能允許或拒絕連線，不能修改 HTTP 請求/回應。  
只有 LIVE 階段函數 （已發佈） 可以與分佈建立關聯。  
每個分佈最多可以有一個連線函數。

## 後續步驟
<a name="connection-function-next-steps"></a>

將連線函數與 CloudFront 分佈建立關聯後，您可以設定選用設定來自訂 mTLS 實作的行為。如需設定其他設定的詳細指示，例如選用的用戶端憑證驗證模式，請參閱 [設定其他設定](configuring-additional-settings.md)。

# 設定其他設定
<a name="configuring-additional-settings"></a>

啟用基本交互 TLS 身分驗證之後，您可以設定其他設定，以針對特定使用案例和需求自訂身分驗證行為。

## 用戶端憑證驗證選用模式
<a name="optional-mode"></a>

CloudFront 提供替代的選用用戶端憑證驗證模式，可驗證呈現的用戶端憑證，但允許存取不存在憑證的用戶端。

### 選用模式行為
<a name="optional-mode-behavior"></a>
+ 授予具有有效憑證的用戶端連線 （拒絕無效的憑證）。
+ 允許在沒有憑證的情況下連線至用戶端
+ 允許透過單一分佈的混合用戶端身分驗證案例。

選用模式非常適合逐步遷移至 mTLS 身分驗證、支援具有憑證的用戶端和沒有憑證的用戶端，或與舊版用戶端保持回溯相容性。

**注意**  
在選用模式中，即使用戶端不存在憑證，連線函數仍會被叫用。這可讓您實作自訂邏輯，例如記錄用戶端 IP 地址，或根據是否顯示憑證套用不同的政策。

### 設定選用模式 （主控台）
<a name="configure-optional-mode-console"></a>

1. 在您的分佈設定中，導覽至**一般**索引標籤，選擇**編輯**。

1. 捲動至**連線**容器中的**檢視器交互身分驗證 (mTLS)** 區段。

1. 針對**用戶端憑證驗證模式**，選取**選用**。

1. 儲存變更。

### 設定選用模式 (AWS CLI)
<a name="configure-optional-mode-cli"></a>

下列範例示範如何設定選用模式：

```
"ViewerMtlsConfig": {
   "Mode": "optional",
   ...other settings
}
```

## 憑證授權單位公告
<a name="ca-advertisement"></a>

AdvertiseTrustStoreCaNames 欄位控制 CloudFront 在 TLS 交握期間是否將信任的 CA 名稱清單傳送給用戶端，協助用戶端選取適當的憑證。

### 設定 CA 公告 （主控台）
<a name="configure-ca-advertisement-console"></a>

1. 在您的分佈設定中，導覽至**一般**索引標籤，選擇**編輯**。

1. 捲動至**連線**容器中的**檢視器交互身分驗證 (mTLS)** 區段。

1. 選取或取消選取**公告信任存放區 CA 名稱**核取方塊。

1. 選擇**儲存變更**。

### 設定 CA 公告 (AWS CLI)
<a name="configure-ca-advertisement-cli"></a>

下列範例示範如何啟用 CA 公告：

```
"ViewerMtlsConfig": {
   "Mode": "required", // or "optional"
   "TrustStoreConfig": {
      "AdvertiseTrustStoreCaNames": true,
      ...other settings
   } 
}
```

## 憑證過期處理
<a name="certificate-expiration-handling"></a>

IgnoreCertificateExpiry 屬性會決定 CloudFront 如何回應過期的用戶端憑證。根據預設，CloudFront 會拒絕過期的用戶端憑證，但您可以視需要將其設定為接受憑證。對於憑證過期且無法立即更新的裝置，通常會啟用此功能。

### 設定憑證過期處理 （主控台）
<a name="configure-expiration-console"></a>

1. 在您的分佈設定中，導覽至**一般**索引標籤，選擇**編輯**。

1. 捲動至**連線**容器的**檢視器交互身分驗證 (mTLS)** 區段。

1. 選取或取消選取**忽略憑證過期日期**核取方塊。

1. 選擇**儲存變更**。

### 設定憑證過期處理 (AWS CLI)
<a name="configure-expiration-cli"></a>

下列範例示範如何忽略憑證過期：

```
"ViewerMtlsConfig": {
  "Mode": "required", // or "optional"
  "TrustStoreConfig": {
     "IgnoreCertificateExpiry": false,
     ...other settings
  }
}
```

**注意**  
**IgnoreCertificateExpiry** 僅適用於憑證有效期限。所有其他憑證驗證檢查仍然適用 （信任鏈、簽章驗證）。

## 後續步驟
<a name="additional-settings-next-steps"></a>

設定其他設定後，您可以設定標頭轉送，將憑證資訊傳遞至原始伺服器、使用 Connection Functions 和 KeyValueStore 實作憑證撤銷，以及啟用連線日誌以進行監控。如需轉送憑證資訊至原始伺服器的詳細資訊，請參閱[轉送標頭至原始伺服器](viewer-mtls-headers.md)。

# 快取政策並轉送至原始伺服器的檢視器 mTLS 標頭
<a name="viewer-mtls-headers"></a>

使用交互 TLS 身分驗證時，CloudFront 可以從用戶端憑證擷取資訊，並將其作為 HTTP 標頭轉送到您的原始伺服器。這可讓您的原始伺服器存取憑證詳細資訊，而無需實作憑證驗證邏輯。

下列標頭可供 用來建立快取行為：


| 標頭名稱 | Description | 範例值 | 
| --- | --- | --- | 
| CloudFront-Viewer-Cert-Serial-Number | 憑證序號的十六進位表示 | 4a：3f：5c：92：d1：e8：7b：6c | 
| CloudFront-Viewer-Cert-Issuer | RFC2253 發行者辨別名稱 (DN) 的字串表示 | CN=rootcamtls.com，OU=rootCA，O=mTLS，L=Seattle，ST=Washington，C=US | 
| CloudFront-Viewer-Cert-Subject | 主旨辨別名稱 (DN) 的 RFC2253 字串表示 | CN=client\$1.com，OU=client-3，O=mTLS，ST=Washington，C=US | 
| CloudFront-Viewer-Cert-Present | 1 （存在） 或 0 （不存在） 表示憑證是否存在。在必要模式下，此值一律為 1。 | 1 | 
| CloudFront-Viewer-Cert-Sha256 | 用戶端憑證的 SHA256 雜湊 | 01fbf94fef5569753420c349f49adbfd80af5275377816e3ab1fb371b29cb586 | 

對於原始伺服器請求，除了上述可用於快取行為的標頭之外，還提供兩個額外的標頭。由於可能的標頭大小，CloudFront-Viewer-Cert-Pem 標頭不會公開至邊緣函數 (Lambda@Edge 或 CloudFront Functions)，而且只會轉送至原始伺服器。


| 標頭名稱 | Description | 範例值 | 
| --- | --- | --- | 
| CloudFront-Viewer-Cert-Validity | notBefore和 notAfter date 的 ISO8601 格式 | CloudFront-Viewer-Cert-Validity：NotBefore=2023-09-21T01：50：17Z；NotAfter=2024-09-20T01：50：17Z | 
| CloudFront-Viewer-Cert-Pem | 分葉憑證的 URL 編碼 PEM 格式 | CloudFront-Viewer-Cert-Pem：-----BEGIN%20CERTIFICATE-----%0AMIIG<...reduced...>NmrUlw%0A-----END%20CERTIFICATE-----%0A | 

## 設定標頭轉送
<a name="configure-header-forwarding"></a>

### 主控台
<a name="configure-headers-console"></a>

在驗證模式中，CloudFront 會自動將 CloudFront-Viewer-Cert-\$1 標頭新增至所有檢視器請求。若要將這些標頭轉送到您的原始伺服器：

1. 在主清單分佈頁面中，選取已啟用檢視器 mTLS 的分佈，然後前往**行為**索引標籤

1. 選取快取行為，然後選擇**編輯**

1. 在**原始伺服器請求政策**區段中，選擇**建立政策**或選取現有政策

1. 確保原始伺服器請求政策中包含下列標頭：
   + CloudFront-Viewer-Cert-Serial-Number
   + CloudFront-Viewer-Cert-Issuer
   + CloudFront-Viewer-Cert-Subject
   + CloudFront-Viewer-Cert-Present
   + Cloudfront-Viewer-Cert-Sha256
   + CloudFront-Viewer-Cert-Validity
   + CloudFront-Viewer-Cert-Pem

1. 選擇**建立** （適用於新政策） 或**儲存變更** （適用於現有政策）

1. 在快取行為中選取政策並儲存變更

### 使用 AWS CLI
<a name="configure-headers-cli"></a>

下列範例示範如何建立原始伺服器請求政策，其中包含用於驗證模式的 mTLS 標頭：

```
aws cloudfront create-origin-request-policy \
  --origin-request-policy-config '{
    "Name": "MTLSHeadersPolicy",
    "HeadersConfig": {
      "HeaderBehavior": "whitelist",
      "Headers": {
        "Quantity": 5,
        "Items": [
          "CloudFront-Viewer-Cert-Serial-Number",
          "CloudFront-Viewer-Cert-Issuer",
          "CloudFront-Viewer-Cert-Subject",
          "CloudFront-Viewer-Cert-Validity",
          "CloudFront-Viewer-Cert-Pem"
        ]
      }
    },
    "CookiesConfig": {
      "CookieBehavior": "none"
    },
    "QueryStringsConfig": {
      "QueryStringBehavior": "none"
    }
  }'
```

## 標頭處理考量
<a name="header-processing-considerations"></a>

使用憑證標頭時，請考慮下列最佳實務：
+ **標頭驗證：**驗證原始伺服器的憑證標頭值作為額外的安全措施
+ **標頭大小限制：**PEM 憑證標頭可以很大，確保您的原始伺服器可以處理它們
+ **快取考量：**在快取金鑰中使用憑證標頭會增加快取分段
+ **跨來源請求：**如果您的應用程式使用 CORS，則您可能需要將其設定為允許憑證標頭

## 後續步驟
<a name="headers-next-steps"></a>

設定標頭轉送之後，您可以使用 CloudFront Connection Functions 和 KeyValueStore 實作憑證撤銷檢查。如需實作撤銷檢查的詳細資訊，請參閱 [使用 CloudFront Connection Function 和 KVS 撤銷](revocation-connection-function-kvs.md)。

# 使用 CloudFront Connection Function 和 KVS 撤銷
<a name="revocation-connection-function-kvs"></a>

您可以結合 CloudFront Connection Functions 與 KeyValueStore，實作交互 TLS 身分驗證的憑證撤銷檢查。此方法提供可擴展的即時憑證撤銷機制，可補充 CloudFront 的內建憑證驗證。

Connection Functions 是在 CloudFront 節點建立 TLS 連線期間執行的 JavaScript 函數，可讓您實作 mTLS 身分驗證的自訂憑證驗證邏輯。如需連線函數的詳細資訊，請參閱 [關聯 CloudFront 連線函數](connection-functions.md)。

## 憑證撤銷如何與 Connection Functions 搭配使用
<a name="how-revocation-works"></a>

CloudFront 的標準憑證驗證會驗證憑證鏈、簽章和過期，但不包含內建憑證撤銷檢查。透過使用連線函數，您可以在 TLS 交握期間實作自訂撤銷檢查。

憑證撤銷程序的運作方式如下：

1. 將撤銷的憑證序號儲存在 CloudFront KeyValueStore 中。

1. 當用戶端提供憑證時，會叫用您的連線函數。

1. 函數會根據 KeyValueStore 檢查憑證的序號。

1. 如果在存放區中找到序號，則會撤銷憑證。

1. 您的函數拒絕已撤銷憑證的連線。

此方法提供跨 CloudFront 全球邊緣網路near-real-time的撤銷檢查。

## 設定已撤銷憑證的 KeyValueStore
<a name="setup-kvs-revoked-certs"></a>

首先，建立 KeyValueStore 以存放已撤銷憑證的序號：

### 建立 KeyValueStore （主控台）
<a name="create-kvs-console"></a>

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**鍵值存放**區。

1. 選擇**建立索引鍵值存放區**。

1. 輸入金鑰值存放區的名稱 （例如，已撤銷憑證）。

1. (選用) 新增描述。

1. 選擇**建立索引鍵值存放區**。

### 建立 KeyValueStore (AWS CLI)
<a name="create-kvs-cli"></a>

下列範例示範如何建立 KeyValueStore：

```
aws cloudfront create-key-value-store \
  --name "revoked-certificates" \
  --comment "Store for revoked certificate serial numbers"
```

## 匯入已撤銷的憑證序號
<a name="import-revoked-serials"></a>

建立 KeyValueStore 之後，您需要匯入已撤銷憑證的序號：

### 準備撤銷資料
<a name="prepare-revocation-data"></a>

使用您撤銷的憑證序號建立 JSON 檔案：

```
{
  "data": [
    {
      "key": "ABC123DEF456",
      "value": ""
    },
    {
      "key": "789XYZ012GHI",
      "value": ""
    }
  ]
}
```

### 從 S3 匯入
<a name="import-from-s3"></a>

1. 將 JSON 檔案上傳至 S3 儲存貯體

1. 將檔案匯入至 KeyValueStore：

   ```
   aws cloudfront create-key-value-store \
     --name "revoked-certificates" \
     --import-source '{
       "SourceType": "S3",
       "SourceARN": "arn:aws:s3:::amzn-s3-demo-bucket1/revoked-serials.json"
     }'
   ```

## 建立用於撤銷檢查的連線函數
<a name="create-revocation-connection-function"></a>

建立連線函數，以檢查憑證序號與 KeyValueStore：

### Connection Function 程式碼範例
<a name="revocation-function-example"></a>

下列範例顯示執行憑證撤銷檢查的連線函數：

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Get client certificate serial number
    const clientSerialNumber = connection.clientCertificate.certificates.leaf.serialNumber;
    
    // Check if the serial number exists in the KeyValueStore
    const isRevoked = await kvsHandle.exists(clientSerialNumber.replaceAll(':', ''));
    
    if (isRevoked) {
        console.log(`Certificate ${clientSerialNumber} is revoked. Denying connection.`);
        connection.logCustomData(`REVOKED:${clientSerialNumber}`);
        connection.deny();
    } else {
        console.log(`Certificate ${clientSerialNumber} is valid. Allowing connection.`);
        connection.allow();
    }
    
}
```

### 建立連線函數 (AWS CLI)
<a name="create-revocation-function-cli"></a>

下列範例示範如何建立與 KeyValueStore 關聯的連線函數：

```
aws cloudfront create-connection-function \
  --name "revocation-checker" \
  --connection-function-config '{
      "Comment": "Certificate revocation checking function",
      "Runtime": "cloudfront-js-2.0",
      "KeyValueStoreAssociations": {
          "Quantity": 1,
          "Items": [
              {
                  "KeyValueStoreARN": "arn:aws:cloudfront::123456789012:key-value-store/revoked-certificates"
              }
          ]
      }
  }' \
  --connection-function-code fileb://revocation-checker.js
```

## 將函數與您的分佈建立關聯
<a name="associate-revocation-function"></a>

建立和發佈連線函數之後，請將其與啟用 mTLS 的 CloudFront 分佈建立關聯，如 [關聯 CloudFront 連線函數](connection-functions.md)一節中所述。

# 使用連線日誌的可觀測性
<a name="connection-logs"></a>

CloudFront 連線日誌提供交互 TLS 身分驗證事件的詳細可見性，可讓您監控憑證驗證、追蹤連線嘗試，以及疑難排解身分驗證問題。

## 什麼是連線日誌？
<a name="what-are-connection-logs"></a>

連線日誌會擷取有關啟用交互 TLS 分佈的 TLS 交握和憑證驗證的詳細資訊。與記錄 HTTP 請求資訊的標準存取日誌不同，連線日誌特別著重於 TLS 連線建立階段，包括：
+ 連線狀態 （成功/失敗）
+ 用戶端憑證詳細資訊
+ TLS 通訊協定和密碼資訊
+ 連線時間指標
+ 來自 Connection Functions 的自訂資料

這些日誌提供憑證型身分驗證事件的全方位可見性，協助您監控安全性、疑難排解問題，並符合合規要求。

## 啟用連線日誌
<a name="enable-connection-logs"></a>

連線日誌僅適用於已啟用交互 TLS 身分驗證的分佈。您可以將連線日誌傳送至多個目的地，包括 CloudWatch Logs、Amazon Data Firehose 和 Amazon S3。

### 先決條件
<a name="connection-logs-prerequisites"></a>

啟用連線日誌之前：
+ 為您的 CloudFront 分佈設定交互 TLS
+ 為您的 CloudFront 分佈啟用連線日誌
+ 確定您擁有所選記錄目的地的必要許可
+ 對於跨帳戶交付，請設定適當的 IAM 政策

### 啟用連線日誌 （主控台）
<a name="enable-connection-logs-console"></a>

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 從分發清單中，選取已啟用 mTLS 的分發。

1. 選擇 **Logging** (日誌記錄) 索引標籤。

1. 選擇**新增**。

1. 選取要接收日誌的服務：
   + **CloudWatch Logs**
   + **Firehose**
   + **Amazon S3**

1. 針對**目的地**，選取所選服務的資源：
   + 針對 CloudWatch Logs，輸入**日誌群組名稱**
   + 對於 Firehose，選取 **Firehose 交付串流**
   + 對於 Amazon S3，輸入**儲存貯體名稱** （選擇性使用字首）

1. (選用) 設定其他設定：
   + **欄位選擇：**選取要包含的特定日誌欄位。
   + **輸出格式：**從 JSON、Plain、w3c、Raw 或 Parquet （僅限 S3) 中選擇。
   + **欄位分隔符號：**指定如何分隔日誌欄位。

1. 選擇 **Save changes (儲存變更)**

### 啟用連線日誌 (AWS CLI)
<a name="enable-connection-logs-cli"></a>

下列範例示範如何使用 CloudWatch API 啟用連線日誌：

```
# Step 1: Create a delivery source
aws logs put-delivery-source \
  --name "cf-mtls-connection-logs" \
  --resource-arn "arn:aws:cloudfront::123456789012:distribution/E1A2B3C4D5E6F7" \
  --log-type CONNECTION_LOGS

# Step 2: Create a delivery destination
aws logs put-delivery-destination \
  --name "s3-destination" \
  --delivery-destination-configuration \
  "destinationResourceArn=arn:aws:s3:::amzn-s3-demo-bucket1"

# Step 3: Create the delivery
aws logs create-delivery \
  --delivery-source-name "cf-mtls-connection-logs" \
  --delivery-destination-arn "arn:aws:logs:us-east-1:123456789012:delivery-destination:s3-destination"
```

**注意**  
使用 CloudWatch API 時，即使將日誌交付至其他區域，您也必須指定美國東部 （維吉尼亞北部） 區域 (us-east-1)。

## 連線日誌欄位
<a name="connection-log-fields"></a>

連線日誌包含每次 TLS 連線嘗試的詳細資訊：


| 欄位 | Description | 範例 | 
| --- | --- | --- | 
| eventTimestamp | 建立連線或失敗時的 ISO 8601 時間戳記 | 1731620046814 | 
| connectionId | TLS 連線的唯一識別符 | oLHiEKbQSn8lkvJfA3D4gFowK3\$1iZ0g4i5nMUjE1Akod8TuAzn5nzg== | 
| connectionStatus |  mTLS 連線嘗試的狀態。  | Success 或 Failed | 
| clientIp | 連線用戶端的 IP 地址 | 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | 
| clientPort | 用戶端使用的連接埠 | 12137 | 
| serverIp | CloudFront 邊緣伺服器的 IP 地址 | 99.84.71.136 | 
| distributionId | CloudFront 分佈 ID | E2DX1SLDPK0123 | 
| distributionTenantId | CloudFront 分佈租用戶 ID （如適用） | dt\$12te1Ura9X3R2iCGNjW123 | 
| tlsProtocol | 使用的 TLS 通訊協定版本 | TLSv1.3 | 
| tlsCipher | 用於連線的 TLS 密碼套件 | TLS\$1AES\$1128\$1GCM\$1SHA256 | 
| tlsHandshakeDuration | TLS 交握的持續時間，以毫秒為單位 | 153 | 
| tlsSni | 來自 TLS 交握的伺服器名稱指示值 | d111111abcdef8.cloudfront.net | 
| clientLeafCertSerialNumber | 用戶端憑證的序號 | 00:b1:43:ed:93:d2:d8:f3:9d | 
| clientLeafCertSubject | 用戶端憑證的主旨欄位 | C=US, ST=WA, L=Seattle, O=Amazon.com, OU=CloudFront, CN=client.test.mtls.net | 
| clientLeafCertIssuer | 用戶端憑證的發行者欄位 | C=US, ST=WA, L=Seattle, O=Amazon.com, OU=CloudFront, CN=test.mtls.net | 
| clientLeafCertValidity | 用戶端憑證的有效期 | NotBefore=2025-06-05T23:28:21Z;NotAfter=2125-05-12T23:28:21Z | 
| connectionLogCustomData | 透過 Connection Functions 新增的自訂資料 | REVOKED:00:b1:43:ed:93:d2:d8:f3:9d | 

## 連線錯誤代碼
<a name="connection-error-codes"></a>

```
Failed:ClientCertMaxChainDepthExceeded
Failed:ClientCertMaxSizeExceeded
Failed:ClientCertUntrusted
Failed:ClientCertNotYetValid
Failed:ClientCertExpired
Failed:ClientCertTypeUnsupported
Failed:ClientCertInvalid
Failed:ClientCertIntentInvalid
Failed:ClientCertRejected
Failed:ClientCertMissing
Failed:TcpError
Failed:TcpTimeout
Failed:ConnectionFunctionError
Failed:ConnectionFunctionDenied
Failed:Internal
Failed:UnmappedConnectionError
```

當連線失敗時，CloudFront 會記錄特定原因代碼：


| Code | Description | 
| --- | --- | 
| ClientCertMaxChainDepthExceeded | 超過憑證鏈深度上限 | 
| ClientCertMaxSizeExceeded | 超過憑證大小上限 | 
| ClientCertUntrusted | 憑證不受信任 | 
| ClientCertNotYetValid | 憑證尚無效 | 
| ClientCertExpired | 憑證已過期 | 
| ClientCertTypeUnsupported | 不支援憑證類型 | 
| ClientCertInvalid | 憑證無效 | 
| ClientCertIntentInvalid | 憑證意圖無效 | 
| ClientCertRejected | 自訂驗證拒絕的憑證 | 
| ClientCertMissing | 憑證遺失 | 
| TcpError |  嘗試建立連線時發生錯誤  | 
| TcpTimeout |  無法在逾時期間內建立連線  | 
| ConnectionFunctionError |  在 Connection Function 執行期間擲回未攔截的例外狀況  | 
| 內部 (Internal) |  發生內部服務錯誤  | 
| UnmappedConnectionError |  發生錯誤，該錯誤不屬於任何其他類別  | 

# 原始伺服器與 CloudFront 的交互 TLS
<a name="origin-mtls-authentication"></a>

相互 TLS 身分驗證 （相互傳輸層安全身分驗證 — mTLS) 是一種安全通訊協定，透過要求雙向憑證型身分驗證來延伸標準 TLS 身分驗證，其中用戶端和伺服器都必須證明其身分，才能建立安全連線。

## 檢視器 mTLS 與原始伺服器 mTLS
<a name="viewer-mtls-vs-origin-mtls"></a>

您可以在檢視器與 CloudFront 分佈 （檢視器 mTLS) 和/或 CloudFront 分佈與原始伺服器 （原始 mTLS) 之間啟用相互身分驗證 (mTLS)。本文件適用於原始伺服器 mTLS 組態。如需檢視器 mTLS 組態，請參閱：[使用 CloudFront 進行相互 TLS 身分驗證 （檢視器 mTLS)原始伺服器與 CloudFront 的交互 TLS](mtls-authentication.md)。

Origin mTLS 可讓 CloudFront 使用用戶端憑證對原始伺服器進行自我驗證。使用原始伺服器 mTLS，您可以確保只有授權的 CloudFront 分佈可以與您的應用程式伺服器建立連線，協助防止未經授權的存取嘗試。

**注意**  
在原始伺服器 mTLS 連線中，CloudFront 充當用戶端，並在 TLS 交握期間將其用戶端憑證呈現給原始伺服器。CloudFront 不會驗證用戶端憑證的有效性或撤銷狀態，這是原始伺服器的責任。您的原始基礎設施必須設定為根據其信任存放區驗證用戶端憑證、檢查憑證過期，並根據您的安全需求執行撤銷檢查 （例如 CRL 或 OCSP 驗證）。CloudFront 的角色僅限於呈現憑證；您的原始伺服器會強制執行所有憑證驗證邏輯和安全性政策。

## 運作方式
<a name="how-origin-mtls-works"></a>

在 CloudFront 與原始伺服器之間的標準 TLS 交握中，只有原始伺服器會呈現憑證，向 CloudFront 證明其身分。使用原始伺服器 mTLS，身分驗證程序會變成雙向。當 CloudFront 嘗試連線到原始伺服器時，CloudFront 會在 TLS 交握期間提供用戶端憑證。您的原始伺服器會在建立安全連線之前，針對其信任存放區驗證此憑證。

## 使用案例
<a name="origin-mtls-use-cases"></a>

Origin mTLS 解決了傳統身分驗證方法建立操作開銷的幾個關鍵安全案例：
+ **混合多雲端安全性** - 您可以保護 CloudFront 與外部託管的原始伺服器 AWS 或公有原始伺服器之間的連線 AWS。這樣就不需要管理 IP 允許清單或自訂標頭解決方案，跨 AWS、內部部署資料中心和第三方供應商提供一致的憑證型身分驗證。媒體公司、零售商和營運分散式基礎設施的企業都受益於整個基礎設施的標準化安全控制。
+ **B2B API 和後端安全性** - 您可以保護後端 APIs和微服務免於直接存取嘗試，同時維護 CloudFront 的效能優勢。具有嚴格身分驗證要求的 SaaS 平台、付款處理系統和企業應用程式可以驗證 API 請求是否僅來自授權的 CloudFront 分發，以防止man-in-the-middle攻擊和未經授權的存取嘗試。

## 重要：原始伺服器需求
<a name="important-origin-server-requirements"></a>

Origin mTLS 需要將原始伺服器設定為支援交互 TLS 身分驗證。您的原始基礎設施必須能夠：
+ 在 TLS 交握期間請求和驗證用戶端憑證
+ 使用發行 CloudFront 用戶端憑證的憑證授權機構憑證維護信任存放區
+ 記錄和監控交互 TLS 連線事件
+ 管理憑證驗證政策和處理身分驗證失敗

CloudFront 會處理用戶端憑證呈現，但您的原始伺服器負責驗證這些憑證和管理交互 TLS 連線。在 CloudFront 中啟用原始伺服器 mTLS 之前，請確定您的原始基礎設施已正確設定。

## 開始使用
<a name="how-origin-mtls-getting-started"></a>

若要使用 CloudFront 實作原始伺服器 mTLS，您需要在 AWS Certificate Manager 中匯入用戶端憑證、將原始伺服器設定為需要交互 TLS，並在 CloudFront 分佈上啟用原始伺服器 mTLS。以下各節提供每個組態任務的step-by-step說明。

**Topics**
+ [檢視器 mTLS 與原始伺服器 mTLS](#viewer-mtls-vs-origin-mtls)
+ [運作方式](#how-origin-mtls-works)
+ [使用案例](#origin-mtls-use-cases)
+ [重要：原始伺服器需求](#important-origin-server-requirements)
+ [開始使用](#how-origin-mtls-getting-started)
+ [使用 Certificate Manager 進行 AWS 憑證管理](origin-certificate-management-certificate-manager.md)
+ [為 CloudFront 分佈啟用原始伺服器交互 TLS](origin-enable-mtls-distributions.md)
+ [搭配原始伺服器交互 TLS 使用 CloudFront 函數](origin-mtls-cloudfront-functions.md)

# 使用 Certificate Manager 進行 AWS 憑證管理
<a name="origin-certificate-management-certificate-manager"></a>

[AWS Certificate Manager (ACM)](https://aws.amazon.com/certificate-manager/) 會存放 CloudFront 在原始伺服器交互 TLS 身分驗證期間提供給原始伺服器的用戶端憑證。

## 憑證授權單位支援
<a name="origin-ca-support"></a>

CloudFront 原始伺服器 mTLS 需要具有延伸金鑰使用 (EKU) 的用戶端憑證，才能進行 TLS 用戶端身分驗證。由於此要求，您必須從憑證授權單位發行憑證，並將其匯入 AWS Certificate Manager。ACM 的自動憑證佈建和續約功能不適用於原始伺服器 mTLS 用戶端憑證。CloudFront 原始伺服器 mTLS 支援來自兩個來源的用戶端憑證：
+ **AWS 私有憑證授權單位：**您可以使用延伸金鑰使用欄位中包含 TLS 用戶端身分驗證的憑證範本 （例如 EndEntityClientAuthCertificate 範本），從 AWS 私有 CA 發行憑證。從 AWS Private CA 發行憑證後，您必須將其匯入美國東部 （維吉尼亞北部） 區域 (us-east-1) 的 ACM。此方法提供 AWS Private CA 的安全優勢，同時讓您控制憑證生命週期管理。
+ **第三方私有憑證授權機構：**您也可以從現有的私有憑證授權機構基礎設施發行憑證，並將其匯入 ACM。這可讓您維護目前的憑證管理程序，同時利用 CloudFront 的原始伺服器 mTLS 功能。憑證必須在延伸金鑰使用欄位中包含 TLS 用戶端身分驗證，而且必須是具有憑證、私有金鑰和憑證鏈的 PEM 格式。

**重要**  
對於 AWS 私有 CA 和第三方 CAs，您需負責監控憑證過期日期，並在過期前將續約的憑證匯入 ACM。ACM 的自動續約功能不適用於用於原始伺服器 mTLS 的匯入憑證。

## 憑證需求和規格
<a name="origin-certificate-requirements"></a>

### 用戶端憑證需求
<a name="origin-ca-cert-format-requirements"></a>
+ **格式：**PEM （隱私權增強郵件） 格式
+ **元件：**憑證、私有金鑰和憑證鏈
+ **憑證鏈深度上限：**3 （分葉憑證 \$1 中繼憑證 \$1 根憑證）
+ **憑證鏈大小上限：**64 KB
+ **憑證大小：**不能超過 96 KB
+ **私有金鑰大小上限：**5 KB (ACM 限制）
+ **每個 CloudFront 分佈建立或更新 API 呼叫可新增或修改的唯一原始伺服器 mTLS 憑證 ARNs 上限：**5
+ **區域：**憑證必須存放在美國東部 （維吉尼亞北部） 區域的 ACM 中 (us-east-1)

### 支援的憑證規格
<a name="origin-supported-cert-specs"></a>
+ **憑證類型：**X.509v3
+ **公有金鑰演算法：**
  + RSA：2048 位元
  + ECDSA：P-256
+ **簽章演算法：**
  + SHA256, SHA384, SHA512搭配 RSA
  + SHA256, SHA384, SHA512搭配 ECDSA
  + SHA256, SHA384, SHA512搭配 RSASSA-PSS 搭配 MGF1
+ **擴充金鑰用量 （必要）：**憑證需要將擴充金鑰用量 (EKU) 擴充功能設定為 TLS 用戶端身分驗證，以確保授權用於 mTLS 目的

### 伺服器憑證需求
<a name="origin-server-certificate-requirements"></a>

在交互 TLS 交握期間，您的原始伺服器必須呈現來自公開信任憑證授權單位的憑證。如需原始伺服器憑證需求的完整詳細資訊，請參閱[搭配 CloudFront 使用 SSL/TLS 憑證的要求](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-cloudfront-to-custom-origin.html#using-https-cloudfront-to-origin-certificate)。

### 請求或匯入憑證
<a name="origin-request-import-certificate"></a>

啟用原始伺服器 mTLS 之前，您必須在 ACM 中擁有可用的用戶端憑證。

#### 從 AWS Private CA 請求和匯入憑證
<a name="request-certificate-aws-private-ca"></a>

事前準備：
+ 您帳戶中設定的 AWS 私有憑證授權機構
+ 從 AWS Private CA 發行憑證的許可
+ 將憑證匯入 ACM 的許可
+ `Extended key usage:TLS web client authentication` 適合您使用案例的[憑證範本](https://docs.aws.amazon.com/privateca/latest/userguide/UsingTemplates.html) ARN
+ 安裝 OpenSSL、 AWS CLI 和 jq （用於剖析 JSON)。

##### 從 PCA 請求憑證並匯入 ACM (AWS CLI)
<a name="request-certificate-cli"></a>

1. 在變數中設定您的私有 CA ARN，以便於重複使用。

   ```
   PCA_ARN="arn:aws:acm-pca:region:account:certificate-authority/12345678..."
   ```

1. 使用 OpenSSL 產生 ECDSA P-256 私有金鑰 (prime256v1 曲線） 和憑證簽署請求 (CSR)，確保使用 節點旗標來保持私有金鑰在 ACM 匯入所需的非加密狀態。

   ```
   openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
       -keyout private.key \
       -out request.csr \
       -subj "/CN=client.example.com"
   ```

1. 將 CSR 提交至您的 AWS Private CA 以發行憑證，這會傳回新發行憑證的 ARN。

   ```
   CERT_ARN=$(aws acm-pca issue-certificate \
       --certificate-authority-arn "$PCA_ARN" \
       --csr fileb://request.csr \
       --signing-algorithm "SHA256WITHECDSA" \
       --validity Value=365,Type="DAYS" \
       --template-arn arn:aws:acm-pca:::template/EndEntityCertificate/V1 \
       --query 'CertificateArn' --output text)
   ```

1. 使用 get-certificate 命令從 AWS PCA 擷取憑證套件，這會傳回分葉憑證和鏈結，然後使用 jq 將其分隔成不同的檔案。

   ```
   # Retrieve the full certificate bundle in JSON format
   aws acm-pca get-certificate \
       --certificate-authority-arn "$PCA_ARN" \
       --certificate-arn "$CERT_ARN" \
       --output json > full_cert.json
   
   # Split into Leaf and Chain
   jq -r '.Certificate' full_cert.json > leaf_cert.pem
   jq -r '.CertificateChain' full_cert.json > cert_chain.pem
   ```

1. 使用 fileb：// 通訊協定將未加密的私有金鑰、分葉憑證和憑證鏈匯入 AWS ACM，以正確處理 CLI 中的二進位檔案資料。

   ```
   aws acm import-certificate \
       --certificate fileb://leaf_cert.pem \
       --private-key fileb://private.key \
       --certificate-chain fileb://cert_chain.pem \
       --region us-east-1 \
       --query 'CertificateArn' \
       --output text
   ```

#### 從第三方 CA 匯入憑證
<a name="import-certificate-third-party-ca"></a>

事前準備：
+ 來自您憑證授權單位的 PEM 格式憑證、未加密私有金鑰和憑證鏈
+ 憑證必須包含 TLS 用戶端身分驗證的延伸金鑰使用量
+ 將憑證匯入 ACM 的許可

##### 將憑證匯入 ACM (AWS CLI)
<a name="import-certificate-cli"></a>

```
aws acm import-certificate \
  --certificate fileb://certificate.pem \
  --private-key fileb://private-key.pem \
  --certificate-chain fileb://certificate-chain.pem \
  --region us-east-1 \
  --query 'CertificateArn' \
  --output text
```

#### 後續步驟
<a name="certificate-next-steps"></a>

在 ACM 中取得或匯入用戶端憑證後，您可以將原始伺服器設定為需要交互 TLS 身分驗證，並在 CloudFront 分佈上啟用原始伺服器 mTLS。如需在 CloudFront 中啟用原始伺服器 mTLS 的說明，請參閱下一節「為 CloudFront 分佈啟用原始伺服器交互 TLS」。

# 為 CloudFront 分佈啟用原始伺服器交互 TLS
<a name="origin-enable-mtls-distributions"></a>

透過 AWS Certificate Manager 取得用戶端憑證，並將原始伺服器設定為需要交互 TLS 之後，您可以在 CloudFront 分佈上啟用原始伺服器 mTLS。

## 先決條件和要求
<a name="origin-mtls-prerequisites-requirements"></a>

在 CloudFront 分佈上啟用原始伺服器 mTLS 之前，請確定您有：
+ 存放在美國東部 （維吉尼亞北部） 區域的 AWS Certificate Manager 中的用戶端憑證 (us-east-1)
+ 原始伺服器設定為需要交互 TLS 身分驗證並驗證用戶端憑證
+ 來自公開信任憑證授權機構的原始伺服器呈現憑證
+ 修改 CloudFront 分佈的許可
+ Origin mTLS 僅適用於 Business、Premium 計劃或 Pay as go 定價計劃。

**注意**  
原始伺服器 mTLS 可以針對自訂原始伺服器 （包括在外部託管的原始伺服器 AWS) 和支援相互 TLS 的 AWS 原始伺服器進行設定，例如 Application Load Balancer 和 API Gateway。

**重要**  
原始伺服器 mTLS 不支援下列 CloudFront 功能：  
**gRPC 流量：**啟用原始伺服器 mTLS 的原始伺服器不支援 gRPC 通訊協定
**WebSocket 連線：**已啟用原始伺服器 mTLS 的原始伺服器不支援 WebSocket 通訊協定
**VPC 原始伺服器：**原始伺服器 mTLS 無法與 VPC 原始伺服器搭配使用
**使用 Lambda@Edge 的原始伺服器請求和原始伺服器回應觸發條件：**原始伺服器 mTLS 不支援原始伺服器請求和原始伺服器回應位置中的 Lambda@Edge 函數
**內嵌 POPs：**內嵌 POPs 不支援原始伺服器 mTLS

## 啟用原始伺服器 mTLS
<a name="origin-enable-mtls-per-origin"></a>

每個原始伺服器組態可讓您為相同分佈中的不同原始伺服器指定不同的用戶端憑證。當您的原始伺服器有不同的身分驗證要求時，此方法可提供最大的彈性。

### 對於新分佈 （主控台）
<a name="origin-enable-mtls-new-distributions"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 選擇**建立分佈**

1. 選取定價計劃：選擇**商務**或**高級**或**隨需付費** （免費計劃不提供原始 mTLS)

1. 在原始伺服器設定區段中，選擇原始伺服器類型為其他

1. 在**原始伺服器設定**區段中，選擇**自訂原始伺服器設定**

1. 設定您的第一個原始伺服器 （網域名稱、通訊協定等）

1. 在原始伺服器組態中，尋找 **mTLS**

1. 將 **mTLS** 切換為開啟

1. 對於**用戶端憑證**，請從 AWS Certificate Manager 選取您的憑證

1. （選用） 使用自己的原始伺服器 mTLS 組態新增其他原始伺服器

1. 完成剩餘的分佈設定，然後選擇**建立分佈**

### 對於現有分佈 （主控台）
<a name="origin-enable-mtls-existing-distributions"></a>

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 從分佈清單中，選取您要修改的分佈。（注意：確保您的分佈在 **Pro 或 Premium 或 Pay As You Go** 定價計劃中。 如果沒有，您必須先升級定價計劃，才能啟用原始伺服器 mTLS)

1. 選擇**原始**伺服器索引標籤

1. 選取您要設定的原始伺服器，然後選擇**編輯**

1. 在原始伺服器設定中，尋找 **mTLS**

1. 將 **mTLS** 切換為開啟

1. 對於**用戶端憑證**，請從 AWS Certificate Manager 選取您的憑證。（注意：只會列出 EKU （擴充金鑰用量） 屬性設為「TLS 用戶端身分驗證」的用戶端憑證）

1. 選擇 **Save changes (儲存變更)**

1. 視需要重複執行其他原始伺服器

## 使用 AWS CLI
<a name="origin-enable-mtls-cli"></a>

對於每個原始伺服器組態，請在每個原始伺服器的組態中指定原始伺服器 mTLS 設定：

```
{
  "Origins": {
    "Quantity": 2,
    "Items": [
      {
        "Id": "origin-1",
        "DomainName": "api.example.com",
        "CustomOriginConfig": {
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only"
        },
        "OriginMtlsConfig": {
          "ClientCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/cert-1"
        }
      },
      {
        "Id": "origin-2",
        "DomainName": "backend.example.com",
        "CustomOriginConfig": {
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only"
        },
        "OriginMtlsConfig": {
          "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/cert-2"
        }
      }
    ]
  }
}
```

**注意**  
如果伺服器未請求用戶端憑證，則 CloudFront 不會提供用戶端憑證，允許連線正常進行。

## 後續步驟
<a name="origin-enable-mtls-next-steps"></a>

在 CloudFront 分佈上啟用原始伺服器 mTLS 之後，您可以使用 CloudFront 存取日誌監控身分驗證事件。

# 搭配原始伺服器交互 TLS 使用 CloudFront 函數
<a name="origin-mtls-cloudfront-functions"></a>

CloudFront Functions 在邊緣提供輕量的無伺服器運算，以自訂內容交付。搭配 CloudFront Functions 使用原始伺服器交互 TLS 時，需要注意有關原始伺服器選取和操作的特定行為和限制。

## 支援的 CloudFront Functions 操作
<a name="supported-cloudfront-functions-operations"></a>

CloudFront Functions 可以透過以下方式與啟用 mTLS 的原始伺服器互動：

### updateRequestOrigin()
<a name="update-request-origin-function"></a>

使用啟用 mTLS 的原始伺服器時，updateRequestOrigin() 函數支援有限的修改：
+ **在原始伺服器 mTLS 原始伺服器之間切換：**您可以更新請求，以路由到使用原始伺服器 mTLS 的不同原始伺服器，前提是兩個原始伺服器都使用**相同的用戶端憑證**。這可讓您實作自訂路由邏輯，同時維持交互 TLS 身分驗證。
+ **停用原始伺服器 mTLS：**您可以透過在 函數`mTLSConfig: 'off'`中設定 ，從啟用 mTLS 的原始伺服器切換到非 mTLS 原始伺服器。這可提供靈活性，以根據請求特性有條件地停用交互 TLS 身分驗證。

#### 範例：在具有相同憑證的原始伺服器 mTLS 原始伺服器之間切換
<a name="example-switching-mtls-origins"></a>

```
function handler(event) {
    var request = event.request;

    // Route to different origin based on request path
    if (request.uri.startsWith('/api/v2')) {
        request.origin = {
            domainName: 'api-v2.example.com',
            customHeaders: {},
            // Both origins must use the same certificate
        };
    }

    return request;
}
```

#### 範例：有條件停用原始伺服器 mTLS
<a name="example-disabling-mtls"></a>

```
function handler(event) {
    var request = event.request;

    // Disable mTLS for specific paths
    if (request.uri.startsWith('/public')) {
        request.origin = {
            domainName: 'public-origin.example.com',
            customHeaders: {},
            mTLSConfig: 'off'
        };
    }

    return request;
}
```

## 不支援的 CloudFront Functions 操作
<a name="unsupported-cloudfront-functions-operations"></a>

下列 CloudFront Functions 操作不支援一般可用性啟用 mTLS 的原始伺服器：

### selectRequestOriginById()
<a name="select-request-origin-by-id-function"></a>

`selectRequestOriginById()` 函數無法選取已啟用原始伺服器 mTLS 的原始伺服器。嘗試使用此函數選取已啟用 mTLS 的原始伺服器會導致驗證錯誤。

如果您的使用案例需要使用原始伺服器 mTLS 進行動態原始伺服器選擇，請`updateRequestOrigin()`改用 ，確保所有目標原始伺服器都使用相同的用戶端憑證。

### createRequestOriginGroup()
<a name="create-request-origin-group-function"></a>

`createRequestOriginGroup()` 函數不支援建立包含啟用 mTLS 之原始伺服器的原始伺服器群組。無法透過 CloudFront Functions 動態建立具有原始 mTLS 原始伺服器的原始伺服器群組。

如果您需要具有原始伺服器 mTLS 的原始伺服器容錯移轉功能，請直接在 CloudFront 分佈設定中設定原始伺服器群組，而不是在函數中動態建立原始伺服器群組。

# 使用已簽署 URL 和已簽署 Cookie 提供私有內容
<a name="PrivateContent"></a>

許多透過網際網路分配內容的公司想要限制對所選使用者的文件、業務資料、媒體串流，或內容的存取許可，例如已付費的使用者。若要使用 CloudFront 安全地提供這類私有內容，請執行以下操作：
+ 請求使用者使用特殊 CloudFront 已簽署的 URL 或已簽署的 Cookie 存取私有內容。
+ 請求您的使用者使用 CloudFront URL 來存取您的內容，而不要使用直接在原始伺服器上存取內容的 URL (例如，Amazon S3 或私有 HTTP 伺服器)。CloudFront URL 非屬必要但建議使用，可防止使用者略過已簽署的 URL 或已簽署的 Cookie 中指定的限制。

如需詳細資訊，請參閱[限制檔案存取](private-content-overview.md)。

## 如何提供私有內容
<a name="private-content-task-list"></a>

若要設定 CloudFront 以提供私有內容，請執行以下任務：

1. (選用建議) 請求您的使用者只能透過 CloudFront 存取內容。您使用的方法取決於您使用的是 Amazon S3 或自訂原始伺服器：
   + ** Amazon S3** – 請參閱 [限制對 Amazon S3 原始伺服器的存取](private-content-restricting-access-to-s3.md)。
   + **自訂原始伺服器** – 請參閱 [在自訂原始伺服器上限制存取檔案](private-content-overview.md#forward-custom-headers-restrict-access)。

   自訂原始伺服器包括 Amazon EC2、設定為網站端點的 Amazon S3 儲存貯體、Elastic Load Balancing，以及您自己的 HTTP Web 伺服器。

1. 指定您要用來建立已簽署 URL 或已簽署 Cookie 的*信任金鑰群組*或*可信簽署者*。建議您使用信任的金鑰群組。如需詳細資訊，請參閱 [指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。

1. 撰寫您的應用程式，使用已簽章的 URL或使用已設定簽章的 Cookie 的 `Set-Cookie` 標頭，以回應來自已獲授權使用者的請求。請遵循下列其中一個主題中的步驟進行：
   + [使用已簽署 URL](private-content-signed-urls.md)
   + [使用已簽署 Cookie](private-content-signed-cookies.md)

   如果您不確定要使用哪個方法，請參閱 [決定使用已簽署 URL 或已簽署 Cookie](private-content-choosing-signed-urls-cookies.md)。

**Topics**
+ [如何提供私有內容](#private-content-task-list)
+ [限制檔案存取](private-content-overview.md)
+ [指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)
+ [決定使用已簽署 URL 或已簽署 Cookie](private-content-choosing-signed-urls-cookies.md)
+ [使用已簽署 URL](private-content-signed-urls.md)
+ [使用已簽署 Cookie](private-content-signed-cookies.md)
+ [用於 Base64 編碼和加密的 Linux 命令和 OpenSSL](private-content-linux-openssl.md)
+ [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)

# 限制檔案存取
<a name="private-content-overview"></a>

您可以透過兩種方式控制使用者對私人內容的存取權：
+ [限制存取 CloudFront 快取中的檔案](#private-content-overview-edge-caches)。
+ 執行以下其中一項以在您的原始伺服器中限制存取檔案：
  + [為您的 Amazon S3 儲存貯體設定原始存取控制 (OAC)](private-content-restricting-access-to-s3.md)。
  + [為私有 HTTP 伺服器 (自訂原始伺服器) 設定自訂標頭。](#forward-custom-headers-restrict-access)

## 限制存取 CloudFront 快取中的檔案
<a name="private-content-overview-edge-caches"></a>

您可以設定 CloudFront，來請求使用者使用*已簽署的 URL* 或*已簽署的 Cookie*，以存取您的檔案。然後，您可以開發應用程式，以建立和分配已簽署的 URL 給驗證過的使用者，或傳送 `Set-Cookie` 標頭，這是經驗證之使用者設定的已簽署 Cookie。(若要提供一些使用者長期存取少量檔案，您還可以手動建立簽章的 URL。) 

當您建立已簽章的 URL 或已簽章的 Cookie，以控制存取您的檔案時，可以指定下列限制：
+ 結束日期和時間，之後 URL 不再有效。
+ (選用) URL 生效的日期和時間。
+ (選用) 可用於存取內容的電腦的 IP 位址或地址範圍。

使用公有-私有金鑰對中的私有金鑰對已簽署的 URL 或已簽署的 Cookie 的一部分進行雜湊和簽名。當有人使用已簽署的 URL 或已簽署的 Cookie 存取檔案時，CloudFront 會比較 URL 或 Cookie 的已簽署和未簽署部分。如果它們不相符， CloudFront 就不會提供檔案。

您必須使用 RSA 2048 或 ECDSA 256 私有金鑰來簽署 URL 或 Cookie。

## 限制對 Amazon S3 儲存貯體中檔案的存取
<a name="private-content-overview-s3"></a>

您可以選擇性地保護 Amazon S3 儲存貯體中的內容，以便使用者可以透過指定的 CloudFront 分佈，但無法使用 Amazon S3 URL 直接進行存取。這可防止某些人繞過 CloudFront 並利用 Amazon S3 URL 來取得您想要限制其存取的內容。使用簽章 URL 不需要此步驟，但我們建議執行此作業。

若要請求使用者透過 CloudFront URL 存取您的內容，請執行下列任務：
+ 授予 CloudFront *原始存取控制*許可，以讀取 S3 儲存貯體中的檔案。
+ 建立原始存取控制，並將其與您的 CloudFront 分佈產生關聯。
+ 移除其他人使用 Amazon S3 URL 讀取檔案的許可。

如需詳細資訊，請參閱 [限制對 Amazon S3 原始伺服器的存取](private-content-restricting-access-to-s3.md) 或 [限制對 Amazon S3 多區域存取點原始伺服器的存取](private-content-restricting-access-to-s3-mrap.md) 。

## 在自訂原始伺服器上限制存取檔案
<a name="forward-custom-headers-restrict-access"></a>

如果您使用自訂原始伺服器，您可以選擇性設定自訂標頭來限制存取。若要使 CloudFront 從自訂原始伺服器取得您的檔案，必須使用標準 HTTP (或 HTTPS) 請求來提供 CloudFront 檔案的存取權限限。然而透過自訂標頭，您可以限制存取內容，讓使用者只能透過 CloudFront，而無法直接進行存取。使用簽章 URL 不需要此步驟，但我們建議執行此作業。

若要請求使用者透過 CloudFront 存取內容，請在您的 CloudFront 分佈中變更下列設定：

**原始伺服器自訂標頭**  
設定 CloudFront 以將自訂標頭轉送至原始伺服器 請參閱 [設定 CloudFront 以將自訂標頭新增到原始伺服器請求](add-origin-custom-headers.md#add-origin-custom-headers-configure)。

**檢視器通訊協定政策**  
設定您的分佈以請求檢視器使用 HTTPS 來存取 CloudFront。請參閱 [檢視器通訊協定政策](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)。

**原始伺服器通訊協定政策**  
將分佈設定為請求 CloudFront 使用與檢視器相同的協定將請求轉傳到原始伺服器。請參閱 [通訊協定 (僅限自訂原始伺服器)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginProtocolPolicy)。

完成這些變更之後，請在自訂原始伺服器上更新應用程式，以僅接受包含您已設定 CloudFront 要傳送之自訂標頭的請求。

**檢視器通訊協定政策**與**原始伺服器通訊協定政策**的組合可確保自訂標頭在傳輸過程中加密。但是，我們建議您定期執行以下任務來輪換 CloudFront 轉傳到您原始伺服器的自訂標頭：

1. 更新您的 CloudFront 分佈以開始將新標頭轉送至您的自訂原始伺服器。

1. 更新您的應用程式以接受新標頭，以確認請求來自 CloudFront。

1. 當檢視器請求不再包括要替換的標頭時，請更新應用程式至不再接受的舊標頭，以確認請求來自 CloudFront。

# 指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者
<a name="private-content-trusted-signers"></a>

**Topics**
+ [在信任的金鑰群組 （建議） 和 之間進行選擇 AWS 帳戶](#choosing-key-groups-or-AWS-accounts)
+ [為您的簽署者建立金鑰對](#private-content-creating-cloudfront-key-pairs)
+ [重新格式化私有金鑰 (僅限 .NET 和 Java)](#private-content-reformatting-private-key)
+ [將簽署者新增至分佈](#private-content-adding-trusted-signers)
+ [輪換金鑰對](#private-content-rotating-key-pairs)

若要建立已簽署 URL 或已簽署 Cookie，您需要 *簽署者*。簽署者是您在 CloudFront 中建立的受信任金鑰群組，或是包含 CloudFront 金鑰對 AWS 的帳戶。建議您使用具有已簽署 URL 和已簽署 Cookie 信任的金鑰群組。如需詳細資訊，請參閱 [在信任的金鑰群組 （建議） 和 之間進行選擇 AWS 帳戶](#choosing-key-groups-or-AWS-accounts)。

簽署者有兩個用途：
+ 一旦您將簽署者新增至您的分佈，CloudFront 就會開始請求檢視器使用已簽署的 URL 或已簽署的 Cookie 來存取您的檔案。
+ 當您建立已簽署 URL 或已簽署 Cookie 時，您可以使用簽署者金鑰對中的私有金鑰對 URL 或 Cookie 的一部分進行簽署。當有人請求受限制的檔案時，CloudFront 會將 URL 或 Cookie 中的簽章與未簽署的 URL 或 Cookie 進行比較，以確認檔案未遭竄改。CloudFront 也可以驗證 URL 或 Cookie 是否有效，也就是好比說到期日期時間到期了嗎？

當您指定簽署者時，您也可以透過將簽署者新增至快取行為，以間接指定需要簽署 URL 或簽署 Cookie 的檔案。如果分佈只有一個快取行為，則使用者必須使用已簽署 URL 或已簽署 Cookie 來存取該分佈中的任何檔案。如果您建立多個快取行為，並將簽署者新增到一些快取行為，而非其他快取行為，則可以請求檢視器使用已簽署 URL 或已簽署 Cookie 來存取這些物件，而非其他檔案。

若要指定允許建立已簽署 URL 或已簽署 Cookie 的簽署者 (私有金鑰)，並將帳戶新增到 CloudFront 分佈中，請執行以下任務：

1. 決定要使用信任的金鑰群組或 AWS 帳戶 做為簽署者。建議您使用信任的金鑰群組。如需詳細資訊，請參閱 [在信任的金鑰群組 （建議） 和 之間進行選擇 AWS 帳戶](#choosing-key-groups-or-AWS-accounts)。

1. 針對您在步驟 1 中選擇的簽署者，建立公有-私有金鑰對。如需詳細資訊，請參閱 [為您的簽署者建立金鑰對](#private-content-creating-cloudfront-key-pairs)。

1. 如果您使用 .NET 或 Java 建立已簽署 URL 或已簽署 Cookie，請重新格式化私有金鑰。如需詳細資訊，請參閱 [重新格式化私有金鑰 (僅限 .NET 和 Java)](#private-content-reformatting-private-key)。

1. 在您要為其建立已簽署 URL 或已簽署 Cookie 的分佈中，指定簽署者。如需詳細資訊，請參閱[將簽署者新增至分佈](#private-content-adding-trusted-signers)。

## 在信任的金鑰群組 （建議） 和 之間進行選擇 AWS 帳戶
<a name="choosing-key-groups-or-AWS-accounts"></a>

若要使用已簽署 URL 或已簽署 Cookie，您需要 *簽署者*。簽署者可以是您在 CloudFront 中建立的可信金鑰群組，也可以是包含 CloudFront 金鑰對的 AWS 帳戶 。基於下列原因，建議您使用信任的金鑰群組：
+ 使用 CloudFront 金鑰群組時，您不需要使用 AWS 帳戶根使用者來管理 CloudFront 已簽章 URLs公有金鑰。 [AWS 最佳實務](https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html#aws_tasks-that-require-root)建議您不需要使用根使用者。
+ 透過 CloudFront 金鑰群組，您可以使用 CloudFront API 管理公有金鑰、金鑰群組和受信任的簽署者。您可以使用 API 自動化金鑰建立和金鑰輪換。當您使用 AWS 根使用者時，必須使用 AWS 管理主控台 來管理 CloudFront 金鑰對，因此您無法自動化程序。
+ 由於您可以使用 CloudFront API 管理金鑰群組，因此您也可以使用 AWS Identity and Access Management (IAM) 許可原則來限制不同使用者可執行的動作。例如，您可以允許使用者上傳公有金鑰，但不能刪除公有金鑰。或者，您可以允許使用者刪除公有金鑰，但只有在符合特定條件時，例如使用多因素驗證、從特定網路傳送請求，或是在特定日期和時間範圍內傳送請求。
+ 透過 CloudFront 金鑰群組，您可以將較多數目的公有金鑰與您的 CloudFront 分佈產生關聯，讓您在使用和管理公有金鑰方面擁有更大的彈性。根據預設，您最多可以將四個金鑰群組與單一分佈產生關聯，而且一個金鑰群組中最多可以有五個公有金鑰。

  當您使用 AWS 帳戶根使用者管理 CloudFront 金鑰對時，每個 AWS 帳戶最多只能有兩個作用中的 CloudFront 金鑰對。

## 為您的簽署者建立金鑰對
<a name="private-content-creating-cloudfront-key-pairs"></a>

您用來建立 CloudFront 已簽署 URL 或已簽署 Cookie 的每個簽署者都必須具有公有-私有金鑰對。簽署者使用其私有金鑰來簽署 URL 或 Cookie，並且 CloudFront 會使用公有金鑰來驗證簽章。

建立金鑰對的方式視您使用信任的金鑰群組做為簽署者 (建議使用) 或是 CloudFront 金鑰對而定。如需詳細資訊，請參閱下列區段。您建立的金鑰對必須符合下列需求：
+ 它必須是 SSH-2 RSA 2048 或 ECDSA 256 金鑰對。
+ 它必須是 base64 編碼的 PEM 格式。

為了協助保護應用程式的安全，建議您定期輪換金鑰對。如需詳細資訊，請參閱 [輪換金鑰對](#private-content-rotating-key-pairs)。

### 為信任的金鑰群組建立金鑰對 (建議使用)
<a name="create-key-pair-and-key-group"></a>

若要為信任的金鑰群組建立金鑰對，請執行下列步驟：

1. 建立公有-私有金鑰對。

1. 將公有金鑰上傳至 CloudFront 。

1. 將公有金鑰新增至 CloudFront 金鑰群組。

如需詳細資訊，請參閱下列程序。<a name="private-content-uploading-cloudfront-public-key-procedure"></a>

**建立一組金鑰對**
**注意**  
下列步驟會使用 OpenSSL 做為建立金鑰對的一種方式來示範。還有許多其他方法可以建立 RSA 或 ECDSA 金鑰對。

1. 請執行下列其中一個範例命令：
   + 下列範例命令會使用 OpenSSL 產生長度為 2048 位元的 RSA 金鑰對，並儲存至名為 `private_key.pem` 的檔案。

     ```
     openssl genrsa -out private_key.pem 2048
     ```
   + 下列範例命令會使用 OpenSSL 產生具備 `prime256v1` 曲線的 ECDSA 金鑰對，並儲存至名為 `private_key.pem` 的檔案。

     ```
     openssl ecparam -name prime256v1 -genkey -noout -out privatekey.pem
     ```

1. 產生的檔案同時包含公有和私有金鑰。下列範例命令會從名為 `private_key.pem` 的檔案擷取公有金鑰。

   ```
   openssl rsa -pubout -in private_key.pem -out public_key.pem
   ```

   您稍後會在下列程序中上傳公有金鑰 (在 `public_key.pem` 檔案中)。

**將公有金鑰上傳至 CloudFront**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽功能表中，選擇**公有金鑰**。

1. 選擇**建立公有金鑰**。

1. 在**建立公有金鑰**視窗中，執行下列動作：

   1. 在**金鑰名稱**中，輸入識別公有金鑰的名稱。

   1. 對於 **Key value** (鍵值)，貼上公有金鑰。如果您遵循上述程序中的步驟，則公有金鑰位於名為 `public_key.pem` 的檔案中。若要複製並貼上公有金鑰的內容，您可以：
      + 在 macOS 或 Linux **cat** 命令列上使用這個命令，如下所示：

        ```
        cat public_key.pem
        ```

        複製該命令的輸出，然後將其貼 **Key value** (鍵值) 欄位中。
      + 使用像「記事本」(在 Windows 上) 或「文字編輯」(在 macOS 上) 等純文字編輯器開啟 `public_key.pem` 檔案。複製檔案內容，然後將其貼到 **Key value** (鍵值) 欄位中。

   1. (選用) 對於**註解**，請新增註解以描述公有金鑰。

   完成時，請選擇**新增**。

1. 記錄公有金鑰 ID。您稍後在建立已簽署 URL 或已簽署 Cookie 時使用它，以做為 `Key-Pair-Id` 欄位的值。

**將公有金鑰新增至金鑰群組**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 在導覽功能表中，選擇**金鑰群組**。

1. 選擇**新增金鑰群組**。

1. 在**建立金鑰群組**頁面上，執行下列動作：

   1. 在**金鑰群組名稱**中，輸入識別金鑰群組的名稱。

   1. (選用) 在**註解**中，輸入註解以描述金鑰群組。

   1. 在**公有金鑰**中，選取要新增至金鑰群組的公有金鑰，然後選擇**新增**。針對您要新增至金鑰群組的每個公有金鑰重複此步驟。

1. 選擇**建立金鑰對**。

1. 記錄金鑰群組名稱。稍後您可以使用它來將金鑰群組與 CloudFront 分佈中的快取行為產生關聯。(在 CloudFront API 中，您可以使用金鑰群組 ID，將金鑰群組與快取行為產生關聯。)

### 建立 CloudFront 金鑰對 （不建議，需要 AWS 帳戶 根使用者）
<a name="create-key-pair-aws-account"></a>

**重要**  
建議您建立信任金鑰群組的公有金鑰，而不是遵循下列步驟。如需建立已簽署 URL 和已簽署 Cookie 之公有金鑰的建議方式，請參閱[為信任的金鑰群組建立金鑰對 (建議使用)](#create-key-pair-and-key-group)。

您可以使用下列方式建立 CloudFront 金鑰對：
+ 在 中建立金鑰對 AWS 管理主控台 並下載私有金鑰。請參見下列步驟：
+ 使用諸如 OpenSSL 的應用程式建立 RSA 金鑰對，並將公有金鑰上傳到 AWS 管理主控台。如需有關建立 RSA 金鑰對的詳細資訊，請參閱 [為信任的金鑰群組建立金鑰對 (建議使用)](#create-key-pair-and-key-group)。<a name="private-content-creating-cloudfront-key-pairs-procedure"></a>

**在 中建立 CloudFront 金鑰對 AWS 管理主控台**

1.  AWS 管理主控台 使用帳戶根使用者的登入資料 AWS 登入 。
**重要**  
IAM 使用者無法建立 CloudFront 金鑰對。您必須使用根使用者登入資料登入，才能建立金鑰對。

1. 選擇您的帳戶名稱，然後選擇**我的安全登入資料**。

1. 選擇 **CloudFront 金鑰對**。

1. 確認您沒有多個作用中的金鑰對。如果您已經有兩個使用中的金鑰對，則無法建立金鑰對。

1. 選擇**建立新的金鑰對**。
**注意**  
您也可以選擇建立自己的金鑰對並上傳公有金鑰。CloudFront 金鑰對支援 1024、2048 或 4096 位元金鑰。

1. 在**建立金鑰對**的對話方塊中，選擇**下載私有金鑰檔案**，然後將檔案儲存在電腦上。
**重要**  
在安全的位置儲存 CloudFront 金鑰對的私有金鑰，並設定該檔案的許可，以便只有所需的管理員可以讀取該金鑰。如果有人取得您的私有金鑰，他們可以產生有效已簽章的 URL 和已簽章的 Cookie 並下載您的內容。您不能再次取得私有金鑰，因此如果您遺失或刪除它，則必須建立新的 CloudFront 金鑰對。

1. 記錄您的金鑰對的金鑰對 ID。（在 中 AWS 管理主控台，這稱為**存取金鑰 ID**。) 您將在建立已簽署 URL 或已簽署 Cookie 時使用它。

## 重新格式化私有金鑰 (僅限 .NET 和 Java)
<a name="private-content-reformatting-private-key"></a>

如果您正使用 .NET 或 Java 以建立已簽署 URL 或已簽署 Cookie，則無法在預設 PEM 格式中，使用金鑰對的私有金鑰來建立簽章。相反地，請執行下列動作：
+ **.NET 框架** – 將私有金鑰轉換為 .NET 框架使用的 XML 格式。有幾種工具可用。
+ **Java** – 將私有金鑰轉換為 DER 格式。執行此操作的一種方法是使用以下 OpenSSL 命令。在下列命令中，`private_key.pem` 是包含 PEM 格式化的私有金鑰的檔案名稱，而且 `private_key.der` 是執行命令之後包含 DER 格式化的私有金鑰的檔案名稱。

  ```
  openssl pkcs8 -topk8 -nocrypt -in private_key.pem -inform PEM -out private_key.der -outform DER
  ```

  為了確保編碼器能正確運作，請將 Bouncy Castle Java 的密碼編譯 API 的 JAR 新增到專案中，然後再新增 Bouncy Castle 供應商。

## 將簽署者新增至分佈
<a name="private-content-adding-trusted-signers"></a>

簽署者是信任的金鑰群組 (建議使用) 或 CloudFront 金鑰對，可為分佈建立已簽署 URL 和已簽署 Cookie。若要在 CloudFront 分佈中使用已簽署 URL 或已簽署 Cookie，您必須指定簽署者。

簽署者與快取行為相關聯。在某些物件或不用於相同分佈之其他檔案下，這允許您要求簽章 URL 或簽章 Cookie。只有和對應快取行為相關聯的檔案，分佈才會要求已簽署的 URL 或 Cookie。

同樣地，簽署者只能為與對應快取行為相關聯的檔案簽署 URL 或 Cookie。例如，如果您有一個快取行為下的簽署者和不同快取行為下的不同簽署者，則這兩個簽署者都不能為與其他快取行為的相關檔案建立簽署 URL 或 Cookie。

**重要**  
在您將簽署者新增至分佈之前，請執行下列動作：  
請仔細定義快取行為中的路徑模式，以及快取行為順序，這樣您就不會讓使用者意外地存取您的內容，也不會讓他們存取您希望所有人都能使用的內容。  
例如，假設請求與兩個快取行為的路徑模式相符合。第一個快取行為不需要已簽章的 URL 或已簽章的 Cookie，而第二個快取行為則需要。使用者將能夠在不使用已簽署的 URL 或已簽署的 Cookie 的情況下存取檔案，因為 CloudFront 處理與第一個符合相關聯的快取行為。  
如需喲歐冠路徑模式的詳細資訊，請參閱 [路徑模式](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)。
對於您已經用來分佈內容的分配內容，請在新增簽署者之前，確定您已準備好開始產生已簽署 URL 和已簽署 Cookie。當您新增簽署者時，CloudFront 會拒絕未包含有效的已簽署 URL 或已簽署 Cookie 請求。

您可以使用 CloudFront 主控台或 CloudFront API 會將簽署者新增至您的分佈。

------
#### [ Console ]

下列步驟說明如何將信任的金鑰群組新增為簽署者。您也可以將 新增 AWS 帳戶 為信任的簽署者，但不建議這麼做。<a name="private-content-adding-trusted-signers-console-procedure"></a>

**使用主控台將簽署者新增至分佈**

1. 記錄要用作信任的簽署者之金鑰群組的金鑰群組 ID。如需詳細資訊，請參閱 [為信任的金鑰群組建立金鑰對 (建議使用)](#create-key-pair-and-key-group)。

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 使用已簽署 URL 或已簽署 Cookie，選擇要保護其檔案的分佈。
**注意**  
若要將簽署者新增至新的發行套件，您可以指定建立發行套件時步驟 6 所述的相同設定。

1. 選擇 **Behaviors (動作)** 索引標籤。

1. 選取快取行為，其路徑模式符合您要使用已簽署 URL 或已簽署 Cookie 保護的檔案，然後選擇**編輯**。

1. 在**編輯行為**頁面上，執行下列動作：

   1. 針對**限制檢視器存取 (使用已簽署 URL 或已簽署 Cookie)**，按一下**是**。

   1. 針對 **Trusted Key Groups or Trusted Signer** (信任的金鑰群組或可信簽署者)，選擇 **Trusted Key Groups** (信任的金鑰群組)。

   1. 在**信任的金鑰群組**中，選擇要新增的金鑰群組，然後選擇**新增**。如果您要新增多個金鑰群組，請重複此步驟。

1. 選擇**是，編輯**以更新快取行為。

------
#### [ API ]

您可以使用 CloudFront API 將信任的金鑰群組新增為簽署者。您可以將簽署者新增至現有分佈或新分佈。在任一情況下，請在 `TrustedKeyGroups` 元素中指定值。

您也可以將 新增 AWS 帳戶 為信任的簽署者，但不建議這麼做。

請參閱 *Amazon CloudFront API 參考*中的下列主題：
+ **更新現有的分佈** - [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)
+ **建立新的分佈** – [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html)

------

## 輪換金鑰對
<a name="private-content-rotating-key-pairs"></a>

建議您定期輪換 (變更) 已簽署網址和已簽署 Cookie 的金鑰對。若要輪換您用來建立已簽署 URL 或已簽署 Cookie 的金鑰對，而不會使尚未到期的無效 URL 或 Cookie，請執行以下任務：

1. 建立新的金鑰對，並將公有金鑰新增至金鑰群組。如需詳細資訊，請參閱 [為信任的金鑰群組建立金鑰對 (建議使用)](#create-key-pair-and-key-group)。

1. 如果您在上一個步驟中建立了新的金鑰群組，[請以簽署者的身分將金鑰群組新增到分佈中](#private-content-adding-trusted-signers)。
**重要**  
請勿從金鑰群組中移除任何現有的公有金鑰，或從分佈中移除任何金鑰群組。請僅加入新的。

1. 使用新金鑰對中的私有金鑰來更新應用程式以建立簽章。確認已簽署 URL 或使用新私有金鑰簽署的 Cookie 正在運作。

1. 等待直到已簽署 URL 或 Cookie 過期，而使用先前的金鑰對。然後從金鑰群組中移除舊的公有金鑰。如果您在步驟 2 中建立新的金鑰群組，請從分佈中移除舊的金鑰群組。

# 決定使用已簽署 URL 或已簽署 Cookie
<a name="private-content-choosing-signed-urls-cookies"></a>

CloudFront 已簽署的 URL 和已簽署的 Cookie 提供了相同的基本函數：允許您控制哪些使用者可以存取您的內容。如果您想要透過 CloudFront 提供私有內容，並且正在嘗試決定是否使用已簽署的 URL 或已簽署的 Cookie，請考慮以下事項。

在以下案例使用已簽章的 URL：
+ 您想要限制對個別檔案的存取，例如，適用於您的應用程式安裝下載。
+ 您的使用者正在使用不支援 Cookie 的用戶端 (例如，自訂 HTTP 用戶端)。

在以下案例使用已簽章的 Cookie：
+ 您想要提供對多個限制檔案的存取，例如，HLS 格式視訊的所有檔案或網站中訂閱者區域的所有檔案。
+ 您不想變更目前的 URL。

如果您目前未使用簽章的 URL，並且您的 (未簽署) URL 包含以下任何查詢字串參數，則不能使用已簽章的 URL 或已簽章的 Cookie：
+ `Expires`
+ `Policy`
+ `Signature`
+ `Key-Pair-Id`
+ `Hash-Algorithm`

CloudFront 假設包含任何這些查詢字串參數的 URL 都是簽署的 URL，因此不會查看已簽署的 Cookie。

## 使用已簽署 URL 和已簽署 Cookie
<a name="private-content-using-signed-urls-and-cookies"></a>

已簽署的網址優先於已簽署的 Cookie。如果您同時使用已簽署的 URL 和已簽署的 Cookie 來控制對相同檔案的存取，並且檢視器使用已簽署的 URL 來請求檔案，CloudFront 將判斷是否只根據已簽署的 URL 將該檔案傳回給檢視器。

# 使用已簽署 URL
<a name="private-content-signed-urls"></a>

已簽章的 URL 包含附加資訊，例如到期日期和時間，以便您更有效地控制對內容的存取。此附加資訊顯示在政策聲明中，該政策聲明基於標準政策或自訂政策。標準和自訂政策之間的差異將在接下來的兩節中說明。

**注意**  
您可使用標準政策建立一些簽章的 URL，並使用自訂政策為相同的分佈建立一些簽章的 URL。

**Topics**
+ [決定對已簽署 URL 使用標準或自訂政策](#private-content-choosing-canned-custom-policy)
+ [已簽署 URL 的工作方式](#private-content-how-signed-urls-work)
+ [決定已簽署 URL 的有效時間](#private-content-overview-choosing-duration)
+ [CloudFront 何時檢查已簽署 URL 中的到期日期和時間](#private-content-check-expiration)
+ [範例程式碼和第三方工具](#private-content-overview-sample-code)
+ [使用標準政策建立已簽署 URL](private-content-creating-signed-url-canned-policy.md)
+ [使用自訂政策建立已簽署 URL](private-content-creating-signed-url-custom-policy.md)

## 決定對已簽署 URL 使用標準或自訂政策
<a name="private-content-choosing-canned-custom-policy"></a>

當您建立已簽章的 URL 時，您將編寫一個 JSON 格式的政策聲明來指定對已簽章的 URL 的限制，例如 URL 的有效時間。您可以使用標準政策或自訂政策。以下是標準和自訂政策的比較：


****  

| 描述 | 標準政策 | 自訂政策 | 
| --- | --- | --- | 
| 您可以重複使用多個檔案的政策聲明。要重複使用政策聲明，您必須在 `Resource` 物件中使用萬用字元。如需詳細資訊，請參閱 [您在使用自訂政策的已簽署 URL 政策陳述式中指定的值](private-content-creating-signed-url-custom-policy.md#private-content-custom-policy-statement-values))。 | 否 | 是 | 
| 您可以指定使用者可以開始存取您的內容的日期和時間。 | 否 | 是 (選用) | 
| 您可以指定使用者無法再存取您的內容的日期和時間。 | 是 | 是 | 
| 您可以指定可以存取您的內容的使用者的 IP 位址或 IP 位址範圍。 | 否 | 是 (選用) | 
| 該已簽章的 URL 包含該政策的 base64 編碼版本，這會導致較長的 URL。 | 否 | 是 | 

如需使用*標準*政策建立已簽署的 URL 的詳細資訊，請參閱 [使用標準政策建立已簽署 URL](private-content-creating-signed-url-canned-policy.md)。

如需使用*自訂*政策建立已簽署的 URL 的詳細資訊，請參閱 [使用自訂政策建立已簽署 URL](private-content-creating-signed-url-custom-policy.md)。

## 已簽署 URL 的工作方式
<a name="private-content-how-signed-urls-work"></a>

以下概述您如何為已簽署的 URL 設定 CloudFront 和 Amazon S3，以及當使用者使用已簽署的 URL 要求檔案時，CloudFront 如何回應。

1. 在您的 CloudFront 分佈中，指定一或多個信任的金鑰群組，其中包含 CloudFront 可用來驗證 URL 簽章的公有金鑰。您可以使用對應的私有金鑰來簽署 URL。

   CloudFront 支援具有 RSA 2048 和 ECDSA 256 金鑰簽章的已簽署 URL。

   如需詳細資訊，請參閱[指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。

1. 開發應用程式以判斷使用者是否應該有權存取您的內容，並為您所要限制存取的應用程式的檔案或某些部分建立的簽署 URL。如需詳細資訊，請參閱下列主題：
   + [使用標準政策建立已簽署 URL](private-content-creating-signed-url-canned-policy.md)
   + [使用自訂政策建立已簽署 URL](private-content-creating-signed-url-custom-policy.md)

1. 使用者請求檔案用於所要請求的簽章 URL。

1. 您的應用程式會驗證使用者是否有權存取檔案：他們已經登入，他們已經支付存取內容的費用，或者他們已經滿足其他一些存取要求。

1. 您的應用程式會建立和傳回已簽章的 URL 給使用者。

1. 已簽章的 URL 允許使用者下載或串流內容。

   這個步驟是自動的；使用者通常不需要執行任何額外操作來存取內容。例如，如果使用者在 Web 瀏覽器l中存取您的內容時，則應用程式會將已簽章的 URL 傳回到瀏覽器。瀏覽器立即使用已簽署的 URL 存取 CloudFront 邊緣快取中的檔案，無需使用者的任何干預。

1. CloudFront 使用公有金鑰來驗證簽章，並確認 URL 尚未遭到篡改。如果簽章無效，請求會遭到拒絕。

   如果簽章有效，CloudFront 將查看 URL 中的政策聲明 (或如果使用的是標準政策，則建構一個聲明) 以確認請求仍然有效。例如，如果您為 URL 指定了開始和結束日期和時間，CloudFront 會確認使用者在您希望允許存取的時間段內嘗試存取您的內容。

   如果請求符合政策聲明中的請求，CloudFront 會執行標準操作：決定檔案是否已經在邊緣上快取，如果需要，將請求轉傳到原始伺服器，並將該檔案傳回給使用者。

**注意**  
如果不帶正負號的 URL 包含查詢字串參數，請務必將這些參數包含在您已簽署 URL 部分中。如果在簽署已簽署 URL 之後，將查詢字串新增此 URL，則 URL 會傳回 HTTP 403 狀態。

## 決定已簽署 URL 的有效時間
<a name="private-content-overview-choosing-duration"></a>

您可以分配私有內容以僅在短時間內使用已簽章的有效 URL (可能只有區區幾分鐘)。有效期很短的簽章 URL 適合於為了特定目的而將內容即時分佈給使用者，例如按需要對客戶作電影租賃或音樂下載的分佈。如果已簽章的 URL 僅在短時間內有效，您可能會希望使用您開發的應用程式自動產生他們。當使用者開始下載檔案或開始播放媒體檔案時，CloudFront 會將 URL 中的到期時間與目前時間進行比較，以判斷 URL 是否仍然有效。

您還可以使用有效期較長的 (可能會持續數年) 已簽章的 URL 分配私有內容。有效期較長的已簽章的 URL 對於向已知使用者分佈私有內容非常有用，例如向投資者分佈業務計畫或向員工分佈培訓教材。您可以開發應用程式，為您產生這些長期簽署的 URL。

## CloudFront 何時檢查已簽署 URL 中的到期日期和時間
<a name="private-content-check-expiration"></a>

CloudFront 會在 HTTP 請求時，在已簽署 URL 中檢查過期日期和時間。如果用戶端在到期前一刻才開始下載大型檔案，則即使在下載期間過期了，下載也應該要完成。如果 TCP 連線中斷並且用戶端在到期時間過後嘗試重新啟動下載，則下載將失敗。

如果用戶端使用範圍 GET 以取得較小型的檔案，則到期時間過後發生的任何 GET 請求都將失敗。如需範圍 GET 的詳細資訊，請參閱 [CloudFront 如何處理物件的部分請求 (範圍 GET)](RangeGETs.md)。

## 範例程式碼和第三方工具
<a name="private-content-overview-sample-code"></a>

如需建立已簽署 URL 的雜湊和已簽署部分的範例程式碼，請參閱下列主題：
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 PHP 建立 URL 簽章](CreateURL_PHP.md)
+ [使用 C\$1 和 .NET 架構建立 URL 簽章](CreateSignatureInCSharp.md)
+ [使用 Java 建立 URL 簽章](CFPrivateDistJavaDevelopment.md)

# 使用標準政策建立已簽署 URL
<a name="private-content-creating-signed-url-canned-policy"></a>

若要使用標準政策建立已簽署 URL，請完成以下步驟。<a name="private-content-creating-signed-url-canned-policy-procedure"></a>

**使用標準政策建立簽章的 URL**

1. 如果您使用 .NET 或 Java 建立簽章的 URL，並且您還沒有將金鑰對的私有金鑰從預設的 .pem 格式重新格式化為與 .NET 或 Java 相容的格式，則現在執行此操作。如需詳細資訊，請參閱[重新格式化私有金鑰 (僅限 .NET 和 Java)](private-content-trusted-signers.md#private-content-reformatting-private-key)。

1. 串連下列值。您可以在此已簽署 URL 範例中使用格式。

   ```
   https://d111111abcdef8.cloudfront.net/image.jpg?color=red&size=medium&Expires=1767290400&Signature=nitfHRCrtziwO2HwPfWw~yYDhUF5EwRunQA-j19DzZrvDh6hQ73lDx~-ar3UocvvRQVw6EkC~GdpGQyyOSKQim-TxAnW7d8F5Kkai9HVx0FIu-5jcQb0UEmatEXAMPLE3ReXySpLSMj0yCd3ZAB4UcBCAqEijkytL6f3fVYNGQI6&Key-Pair-Id=K2JCJMDEHXQW5F&Hash-Algorithm=SHA256
   ```

   移除所有空格 (包括標籤和換行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。所有值都有一個 `String` 類型。  
**1. *檔案的基本 URL***  
如果您未使用簽署的 URL，包括您自我的查詢字串參數 (如果有)，則基本 URL 是您用來存取檔案的 CloudFront URL。在上述範例中，基本 URL 為 `https://d111111abcdef8.cloudfront.net/image.jpg`。如需有關分佈的 URL 格式的詳細資訊，請參閱 [自訂 CloudFront 中檔案的 URL 格式](LinkFormat.md)。  
   + 下列 CloudFront URL 適用於分佈中的映像檔案 (使用 CloudFront 網域名稱)。請注意，`image.jpg` 位於 `images` 目錄中。在 URL 中檔案的路徑必須與 HTTP 伺服器或 Amazon S3 儲存貯體中的檔案的路徑相符。

     `https://d111111abcdef8.cloudfront.net/images/image.jpg`
   + 下列 CloudFront URL 包含查詢字串：

     `https://d111111abcdef8.cloudfront.net/images/image.jpg?size=large`
   + 下列 CloudFront URL 適用於分佈中的圖片檔案。同時使用替代網域名稱。第二個包含查詢字串：

     `https://www.example.com/images/image.jpg`

     `https://www.example.com/images/image.jpg?color=red`
   + 以下 CloudFront URL 用於分佈中使用備用網域名稱和 HTTPS 通訊協定的圖片檔案：

     `https://www.example.com/images/image.jpg`  
** 2. `?` **  
`?` 代表基本 URL 後面所接的查詢字串參數。即使您未指定任何查詢參數，也請包含 `?`。  
您可以依任何順序指定下列查詢參數。  
**3. *您的查詢字串參數 (如果有的話)*`&`**  
(選用) 您可以輸入自己的查詢字串參數。若要這樣做，請在每個參數之間新增 and (`&`)，例如 `color=red&size=medium`。您可以在 URL 內以任何順序指定查詢字串參數。  
您的查詢字串參數無法命名為 `Expires`、`Key-Pair-Id`、 `Signature`或 `Hash-Algorithm`。  
** 4. `Expires=`*Unix 時間格式的日期和時間 (以秒為單位) 和國際標準時間 (UTC)***  
您希望 URL 停止允許存取檔案的日期和時間。  
以 Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 指定過期日期和時間。例如，2026 年 1 月 1 日上午 10:00 UTC 會以 Unix 時間格式轉換為 `1767290400`，如本主題開頭的範例所示。  
若要使用 epoch 時間，請為不晚於 `9223372036854775807` 的日期指定 64 位元整數 (2262 年 4 月 11 日星期五 23:47:16.854 UTC)。  
  
如需世界協調時間的詳細資訊，請參閱 [RFC 3339、網際網路上的日期和時間：時間戳記](https://tools.ietf.org/html/rfc3339)。  
** 5. `&Signature=`*政策陳述式的雜湊和簽署版本***  
JSON 政策聲明的雜湊、簽章和 base64-encoded 版本。如需詳細資訊，請參閱[為使用標準政策的已簽署 URL 建立簽章](#private-content-canned-policy-creating-signature)。  
** 6. `&Key-Pair-Id=`*CloudFront 公有金鑰的公有金鑰 ID，您用來產生簽章的對應私有金鑰***  
CloudFront 公有金鑰的 ID，例如 `K2JCJMDEHXQW5F`。公有金鑰 ID 會告訴 CloudFront 要使用哪個公有金鑰來驗證已簽署的 URL。CloudFront 將簽章中的資訊與政策聲明中的資訊進行比較，以驗證該 URL 尚未遭到篡改。  
此公有金鑰必須屬於分佈中信任的簽署者金鑰群組。如需詳細資訊，請參閱[指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。  
** 7. `&Hash-Algorithm=`*SHA1 或 SHA256***  
（選用） 用來建立簽章的雜湊演算法。支援的值為 `SHA1` 和 `SHA256`。如果您未指定此參數，CloudFront 會預設為 `SHA1`。

## 為使用標準政策的已簽署 URL 建立簽章
<a name="private-content-canned-policy-creating-signature"></a>

若要為使用標準政策的已簽署 URL 建立簽章，請完成下列程序。

**Topics**
+ [為使用標準政策的已簽署 URL 建立政策陳述式](#private-content-canned-policy-creating-policy-statement)
+ [為使用標準政策的已簽署 URL 建立簽章](#private-content-canned-policy-signing-policy-statement)

### 為使用標準政策的已簽署 URL 建立政策陳述式
<a name="private-content-canned-policy-creating-policy-statement"></a>

當您使用標準政策建立已簽章的 URL 時，`Signature` 參數是政策聲明的雜湊和簽章版本。對於使用標準政策的簽章的 URL，您不會將政策聲明包括在 URL 中，就像您使用自訂政策的已簽章的 URL 一樣。若要建立政策聲明，請執行下列程序。<a name="private-content-canned-policy-creating-policy-statement-procedure"></a>

**為使用標準政策的已簽章的 URL 建立政策聲明**

1. 建構政策聲明，使用下列 JSON 格式，並使用 UTF-8 字元編碼。完全按照規定包含所有標點符號和其他常值。如需有關 `Resource` 和 `DateLessThan` 參數的詳細資訊，請參閱 [您在使用標準政策的已簽署 URL 的政策陳述式中指定的值](#private-content-canned-policy-statement-values)。

   ```
   {
       "Statement": [
           {
               "Resource": "base URL or stream name",
               "Condition": {
                   "DateLessThan": {
                       "AWS:EpochTime": ending date and time in Unix time format and UTC
                   }
               }
           }
       ]
   }
   ```

1. 從政策陳述式中刪除所有空格 (包括標籤和新行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。

#### 您在使用標準政策的已簽署 URL 的政策陳述式中指定的值
<a name="private-content-canned-policy-statement-values"></a>

當您為標準政策建立政策聲明時，您可以指定以下值。

**資源**  
您只能為 `Resource` 指定一個值。
包含查詢字串的基本 URL，如果有的話，但不包括 CloudFront `Expires`、`Key-Pair-Id`、 `Signature`和 `Hash-Algorithm` 參數，例如：  
`https://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes`  
注意下列事項：  
+ **通訊協定** – 此值必須以 `http://` 或 `https://` 開頭。
+ **查詢字串參數** – 如果沒有查詢字串參數，請省略問號。
+ **替代網域名稱** – 如果在 URL 中指定了替代網域名稱 (CNAME)，則在引用網頁或應用程式中的檔案時，必須指定替代網域名稱。請勿為物件指定 Amazon S3 URL。

**DateLessThan**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的到期日期和時間。例如，2026 年 1 月 1 日上午 10:00 UTC 以 Unix 時間格式轉換為 1767290400。  
此值必須與已簽章的 URL 中的 `Expires` 查詢字串參數的值相符。不要將值括在引號中。  
如需詳細資訊，請參閱 [CloudFront 何時檢查已簽署 URL 中的到期日期和時間](private-content-signed-urls.md#private-content-check-expiration)。

#### 使用標準政策的已簽署 URL 範例政策陳述式
<a name="private-content-canned-policy-creating-policy-statement-example"></a>

當您在已簽署 URL 中使用以下範例政策陳述式時，使用者在到 UTC 2026 年 1 月 1 日上午 10:00 之前可以存取檔案 `https://d111111abcdef8.cloudfront.net/horizon.jpg`：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/horizon.jpg?size=large&license=yes",
            "Condition": {
                "DateLessThan": {
                    "AWS:EpochTime": 1767290400
                }
            }
        }
    ]
}
```

### 為使用標準政策的已簽署 URL 建立簽章
<a name="private-content-canned-policy-signing-policy-statement"></a>

若要在已簽章的 URL 中建立 `Signature` 參數的值，請對您在 [為使用標準政策的已簽署 URL 建立政策陳述式](#private-content-canned-policy-creating-policy-statement) 中建立的政策聲明進行雜湊和簽署。

如需有關如何對政策聲明進行雜湊、簽章和編碼的詳細資訊和範例，請參閱：
+ [用於 Base64 編碼和加密的 Linux 命令和 OpenSSL](private-content-linux-openssl.md)
+ [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)

**注意**  
連結的範例預設使用 SHA-1。若要改為使用 SHA-256，請在 OpenSSL 命令`sha256`中將 取代`sha1`為 ，並在簽章的 URL 中包含`Hash-Algorithm=SHA256`查詢參數。<a name="private-content-canned-policy-creating-signature-download-procedure"></a>

**選項 1：使用標準政策建立簽章**

1. 使用 SHA-1 或 SHA-256 雜湊函數和產生的 RSA 或 ECDSA 私有金鑰來雜湊並簽署您在程序 中建立的政策陳述式[為使用標準政策的已簽章的 URL 建立政策聲明](#private-content-canned-policy-creating-policy-statement-procedure)。使用不再包含空格之政策陳述式的版本。

   如果您使用 SHA-256，則必須在簽章的 URL `&Hash-Algorithm=SHA256`中包含 。

   對於雜湊函數所需的私有金鑰，使用其公有金鑰在活動的信任金鑰組中的私有金鑰進行分佈。
**注意**  
用於雜湊和簽名政策聲明的方法取決於您的程式設計語言和平台。如需程式碼範例，請參閱 [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)。

1. 從雜湊和已簽署字串中移除所有空格 (包括索引標籤和新行字元)。

1. 使用 MIME base64 編碼的 Base64-encode 字串。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html)

1. 在 `&Signature=` 之後，將結果值附加到已簽章的 URL，然後返回到[使用標準政策建立簽章的 URL](#private-content-creating-signed-url-canned-policy-procedure)以完成已簽章的 URL 的各個部分的連接。

# 使用自訂政策建立已簽署 URL
<a name="private-content-creating-signed-url-custom-policy"></a>

若要使用自訂政策建立簽章的 URL，請完成以下程序。<a name="private-content-creating-signed-url-custom-policy-procedure"></a>

**使用自訂政策建立簽章的 URL**

1. 如果您使用 .NET 或 Java 建立簽章的 URL，並且您還沒有將金鑰對的私有金鑰從預設的 .pem 格式重新格式化為與 .NET 或 Java 相容的格式，則現在執行此操作。如需詳細資訊，請參閱[重新格式化私有金鑰 (僅限 .NET 和 Java)](private-content-trusted-signers.md#private-content-reformatting-private-key)。

1. 串連下列值。您可以在此已簽署 URL 範例中使用格式。

   

   ```
   https://d111111abcdef8.cloudfront.net/image.jpg?color=red&size=medium&Policy=eyANCiAgICEXAMPLEW1lbnQiOiBbeyANCiAgICAgICJSZXNvdXJjZSI6Imh0dHA6Ly9kemJlc3FtN3VuMW0wLmNsb3VkZnJvbnQubmV0L2RlbW8ucGhwIiwgDQogICAgICAiQ29uZGl0aW9uIjp7IA0KICAgICAgICAgIklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIyMDcuMTcxLjE4MC4xMDEvMzIifSwNCiAgICAgICAgICJEYXRlR3JlYXRlclRoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTI5Njg2MDE3Nn0sDQogICAgICAgICAiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjEyOTY4NjAyMjZ9DQogICAgICB9IA0KICAgfV0gDQp9DQo&Signature=nitfHRCrtziwO2HwPfWw~yYDhUF5EwRunQA-j19DzZrvDh6hQ73lDx~-ar3UocvvRQVw6EkC~GdpGQyyOSKQim-TxAnW7d8F5Kkai9HVx0FIu-5jcQb0UEmatEXAMPLE3ReXySpLSMj0yCd3ZAB4UcBCAqEijkytL6f3fVYNGQI6&Key-Pair-Id=K2JCJMDEHXQW5F&Hash-Algorithm=SHA256
   ```

   移除所有空格 (包括標籤和換行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。所有值都有一個 `String` 類型。  
**1. *檔案的基本 URL***  
如果您未使用簽署的 URL，包括您自我的查詢字串參數 (如果有)，則基本 URL 是您用來存取檔案的 CloudFront URL。在上述範例中，基本 URL 為 `https://d111111abcdef8.cloudfront.net/image.jpg`。如需有關分佈的 URL 格式的詳細資訊，請參閱 [自訂 CloudFront 中檔案的 URL 格式](LinkFormat.md)。  
以下範例說明您為分佈指定的值。  
   + 下列 CloudFront URL 適用於分佈中的映像檔案 (使用 CloudFront 網域名稱)。請注意，`image.jpg` 位於 `images` 目錄中。在 URL 中檔案的路徑必須與 HTTP 伺服器或 Amazon S3 儲存貯體中的檔案的路徑相符。

     `https://d111111abcdef8.cloudfront.net/images/image.jpg`
   + 下列 CloudFront URL 包含查詢字串：

     `https://d111111abcdef8.cloudfront.net/images/image.jpg?size=large`
   + 下列 CloudFront URL 適用於分佈中的圖片檔案。兩種都使用備用網域名稱，第二個包含查詢字串：

     `https://www.example.com/images/image.jpg`

     `https://www.example.com/images/image.jpg?color=red`
   + 以下 CloudFront URL 用於分佈中使用備用網域名稱和 HTTPS 通訊協定的圖片檔案：

     `https://www.example.com/images/image.jpg`  
**2. `?` **  
`?` 代表基本 URL 後面所接的查詢字串參數。即使您未指定任何查詢參數，也請包含 `?`。  
您可以依任何順序指定下列查詢參數。  
**3. *您的查詢字串參數 (如果有的話)*`&`**  
(選用) 您可以輸入自己的查詢字串參數。若要這樣做，請在每個參數之間新增 and (&)，例如 `color=red&size=medium`。您可以在 URL 內以任何順序指定查詢字串參數。  
您的查詢字串參數無法命名為 `Policy`、`Key-Pair-Id`、 `Signature`或 `Hash-Algorithm`。
如果加入自己的參數，請在每個參數的後面附加一個 `&`，包括最後一個參數。  
**4. `Policy=`*base64 編碼版本的政策陳述式***  
您的政策陳述式採用 JSON 格式，刪除了空格，然後使用 base64 編碼。如需詳細資訊，請參閱[為使用自訂政策的已簽署 URL 建立政策陳述式](#private-content-custom-policy-statement)。  
政策陳述式可控制簽署的 URL 授予使用者的存取權限。它包括檔案的 URL、到期日期和時間、URL 變成有效的選擇性日期和時間，以及允許存取檔案的選用 IP 位址或 IP 位址範圍。  
**5. `&Signature=`*政策陳述式的雜湊和簽署版本***  
JSON 政策聲明的雜湊、簽章和 base64-encoded 版本。如需詳細資訊，請參閱[為使用自訂準政策的已簽署 URL 建立簽章](#private-content-custom-policy-creating-signature)。  
**6. `&Key-Pair-Id=`*CloudFront 公有金鑰的公有金鑰 ID，您用來產生簽章的對應私有金鑰***  
CloudFront 公有金鑰的 ID，例如 `K2JCJMDEHXQW5F`。公有金鑰 ID 會告訴 CloudFront 要使用哪個公有金鑰來驗證已簽署的 URL。CloudFront 將簽章中的資訊與政策聲明中的資訊進行比較，以驗證該 URL 尚未遭到篡改。  
此公有金鑰必須屬於分佈中信任的簽署者金鑰群組。如需詳細資訊，請參閱[指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。  
**7. `&Hash-Algorithm=`*SHA1 或 SHA256***  
（選用） 用來建立簽章的雜湊演算法。支援的值為 `SHA1` 和 `SHA256`。如果您未指定此參數，CloudFront 會預設為 `SHA1`。

## 為使用自訂政策的已簽署 URL 建立政策陳述式
<a name="private-content-custom-policy-statement"></a>

請完成以下步驟，以為使用自訂政策之簽署的 URL 建立政策陳述式。

如需以各種方式控制對檔案存取的政策聲明範例，請參閱 [使用自訂政策的已簽署 URL 範例政策陳述式](#private-content-custom-policy-statement-examples)。<a name="private-content-custom-policy-creating-policy-procedure"></a>

**為使用自訂政策的已簽章的 URL 建立政策聲明**

1. 使用下列 JSON 格式建構政策聲明。使用您自己的值取代小於 (`<`) 和大於 (`>`) 符號及其中的描述。如需詳細資訊，請參閱[您在使用自訂政策的已簽署 URL 政策陳述式中指定的值](#private-content-custom-policy-statement-values)。

   ```
   {
       "Statement": [
           {
               "Resource": "<Optional but recommended: URL of the file>",
               "Condition": {
                   "DateLessThan": {
   	                "AWS:EpochTime": <Required: ending date and time in Unix time format and UTC>
                   },
                   "DateGreaterThan": {
   	                "AWS:EpochTime": <Optional: beginning date and time in Unix time format and UTC>
                   },
                   "IpAddress": {
   	                "AWS:SourceIp": "<Optional: IP address>"
                   }
               }
           }
       ]
   }
   ```

   注意下列事項：
   + 您只能在政策中包含一個陳述式。
   + 使用 UTF-8 字元編碼。
   + 完全按照規定包含所有標點符號和參數名稱。不接受參數名稱的縮寫。
   + `Condition` 部分的參數順序不重要。
   + 如需有關 `Resource`、`DateLessThan`、`DateGreaterThan` 和 `IpAddress` 值的詳細資訊，請參閱 [您在使用自訂政策的已簽署 URL 政策陳述式中指定的值](#private-content-custom-policy-statement-values)。

1. 從政策陳述式中刪除所有空格 (包括標籤和新行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。

1. 使用 MIME base64 編碼 Base64-encode 政策聲明。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html)

1. 在 `Policy=` 之後，將結果值附加到已簽章的 URL。

1. 透過政策聲明進行雜湊、簽名和 base64-encoding 來建立用於簽章 URL 的簽章。如需詳細資訊，請參閱[為使用自訂準政策的已簽署 URL 建立簽章](#private-content-custom-policy-creating-signature)。

### 您在使用自訂政策的已簽署 URL 政策陳述式中指定的值
<a name="private-content-custom-policy-statement-values"></a>

當您為自訂政策建立政策聲明時，您可以指定以下值。

**資源**  
URL，包括任何查詢字串，但不包括 CloudFront `Policy`、`Key-Pair-Id`、 `Signature`和 `Hash-Algorithm` 參數。例如：  
`https://d111111abcdef8.cloudfront.net/images/horizon.jpg\?size=large&license=yes`  
您只能為 `Resource` 指定一個 URL 值。  
您可以省略政策中的 `Resource` 參數，但如此便代表任何擁有已簽署 URL 的人，都可以存取與您建立已簽署 URL 的金鑰對關聯的*任何*分佈中的*所有*檔案。
注意下列事項：  
+ **通訊協定** – 此值必須以 `http://`、`https://` 或 `*://` 開頭。
+ **查詢字串參數** – 如果 URL 具有查詢字串參數，請勿使用反斜線字元 (`\`) 來逸出開始查詢字串的問號字元 (`?`)。例如：

  `https://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes`
+ **萬用字元** – 您可以在政策中的 URL 中使用萬用字元。支援下列萬用字元：
  + 星號 (`*`)，符合零或更多字元
  + 問號 (`?`)，剛好符合一個字元

  在 CloudFront 將政策中的 URL 與 HTTP 要求中的 URL 相符時，政策中的 URL 會分為四個區段－通訊協定、網域、路徑和查詢字串)，如下所示：

  `[protocol]://[domain]/[path]\?[query string]`

  當您在政策的 URL 中使用萬用字元時，萬用字元比對只會套用在包含萬用字元的區段邊界內。例如，在政策中考量此 URL：

  `https://www.example.com/hello*world`

  在此範例中，星號萬用字元 (`*`) 僅適用於路徑區段中，因此它符合 URL `https://www.example.com/helloworld` 和 `https://www.example.com/hello-world`，但與 URL `https://www.example.net/hello?world` 不相符。

  下列例外適用於萬用字元相符的區段邊界：
  + 路徑區段中的結尾星號表示查詢字串區段中的星號。例如，`http://example.com/hello*` 等同於 `http://example.com/hello*\?*`。
  + 網域區段域部分中的結尾星號表示路徑和查詢字串部分中都有星號。例如，`http://example.com*` 等同於 `http://example.com*/*\?*`。
  + 政策中的 URL 可以省略通訊協定區段，並在網域區段中以星號開頭。在這種情況下，通訊協定部分暗中設為星號。例如，策略 `*example.com` 中的 URL 等同於 `*://*example.com/`。
  + 星號本身 (`"Resource": "*"`) 符合任何 URL。

  例如，策略 `https://d111111abcdef8.cloudfront.net/*game_download.zip*` 中的值:符合下列所有 URL：
  + `https://d111111abcdef8.cloudfront.net/game_download.zip`
  + `https://d111111abcdef8.cloudfront.net/example_game_download.zip?license=yes`
  + `https://d111111abcdef8.cloudfront.net/test_game_download.zip?license=temp`
+ **替代網域名稱** – 如果在 URL 中指定了替代網域名稱 (CNAME)，則在引用網頁或應用程式中的檔案時，必須指定替代網域名稱。請勿在政策中為檔案指定 Amazon S3 URL。

**DateLessThan**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的到期日期和時間。在政策中，不要將值括在引號中。如需世界協調時間的詳細資訊，請參閱[網際網路上的日期和時間：時間戳記](https://tools.ietf.org/html/rfc3339)。  
例如，2023 年 1 月 31 日上午 10:00 UTC 以 Unix 時間格式轉換為 1675159200。  
這是 `Condition` 部分中唯一需要的參數。CloudFront 請求這個值，以防止使用者永久存取您的私有內容。  
如需詳細資訊，請參閱[CloudFront 何時檢查已簽署 URL 中的到期日期和時間](private-content-signed-urls.md#private-content-check-expiration)

**DateGreaterThan (選用)**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的選用日期和時間。不允許使用者在指定的日期和時間之前存取檔案。不要將值括在引號中。

**IpAddress (選用)**  
提出 HTTP 請求的用戶端 IP 位址。注意下列事項：  
+ 要允許任何 IP 位址存取該檔案，請省略 `IpAddress` 參數。
+ 您可以指定一個 IP 位址或一個 IP 位址範圍。如果用戶端的 IP 位址位於兩個不同的範圍之一，則無法設定政策以允許存取。
+ 若要允許從單一 IP 位址存取，您需要指定：

  `"`*IPv4 IP 位址*`/32"`
+ 必須以標準 IPv4 CIDR 格式指定 IP 位址範圍 (例如 `192.0.2.0/24`)。如需詳細資訊，請參閱[《無類別域間路由 (CIDR)：網際網路地址指派和彙總計劃》](https://tools.ietf.org/html/rfc4632)。
**重要**  
不支援 IPv6 格式的 IP 位址，例如 2001:0db8:85a3::8a2e:0370:7334。

  如果您使用的是包括 `IpAddress` 的自訂政策，請不要為分佈啟用 IPv6。如果您希望透過 IP 位址限制對某些內容的存取，並支援對其他內容的 IPv6 請求，則可以建立兩個分佈。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [啟用 IPv6 (檢視器請求)](DownloadDistValuesGeneral.md#DownloadDistValuesEnableIPv6)。

## 使用自訂政策的已簽署 URL 範例政策陳述式
<a name="private-content-custom-policy-statement-examples"></a>

以下範例說明政策聲明說明了如何控制對特定檔案的存取、目錄中的所有檔案，或與金鑰對 ID 相關聯的所有檔案。此範例還會說明了如何控制來自個別 IP 位址或各種 IP 位址的存取，以及如何防止使用者在指定的日期和時間過期後使用簽章 URL。

如果複製並貼上這些範例中的任何一項，請刪除所有空格 (包括索引標籤和換行符號字元)、用您自我的值取代該值，並在大括弧 (`}`) 的後面加上換行字元。

如需詳細資訊，請參閱[您在使用自訂政策的已簽署 URL 政策陳述式中指定的值](#private-content-custom-policy-statement-values)。

**Topics**
+ [範例政策陳述式：從一個 IP 位址範圍存取一個檔案](#private-content-custom-policy-statement-example-one-object)
+ [範例政策陳述式：從一個 IP 位址範圍存取目錄中的所有檔案](#private-content-custom-policy-statement-example-all-objects)
+ [範例政策陳述式：從一個 IP 位址存取與金鑰對 ID 相關的所有檔案](#private-content-custom-policy-statement-example-one-ip)

### 範例政策陳述式：從一個 IP 位址範圍存取一個檔案
<a name="private-content-custom-policy-statement-example-one-object"></a>

以下範例自訂政策在已簽署的 URL 中指定使用者在到 UTC 2023 年 1 月 31 日上午 10:00 之前可以從 `192.0.2.0/24` 範圍內的 IP 位址存取檔案 `https://d111111abcdef8.cloudfront.net/game_download.zip`：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/game_download.zip",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.0/24"
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1675159200
                }
            }
        }
    ]
}
```

### 範例政策陳述式：從一個 IP 位址範圍存取目錄中的所有檔案
<a name="private-content-custom-policy-statement-example-all-objects"></a>

以下範例自訂政策允許您為 `training` 目錄中的任何檔案建立簽章的 URL，如 `Resource` 參數中的 (`*`) 萬用字元所示。使用者在到 UTC 2023 年 1 月 31 日上午 10:00 之前可以從 `192.0.2.0/24` 範圍內的 IP 位址存取該檔案：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/training/*",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.0/24"
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1675159200
                }
            }
        }
    ]
}
```

您使用此政策的每個已簽章的 URL 都包括一個識別特定的檔案的基本 URL，例如：

`https://d111111abcdef8.cloudfront.net/training/orientation.pdf`

### 範例政策陳述式：從一個 IP 位址存取與金鑰對 ID 相關的所有檔案
<a name="private-content-custom-policy-statement-example-one-ip"></a>

以下範例自訂政策允許您為與任何分佈關聯的任何檔案建立簽章的 URL，如 `Resource` 參數中的 (`*`) 萬用字元所示。已簽署的 URL 必須使用 `https://` 通訊協定，而不是 `http://`。使用者必須使用 IP 位址 `192.0.2.10/32`。(CIDR 表示法中的 `192.0.2.10/32` 值是指單個 IP 位址 `192.0.2.10`。) 這些檔案只能在 2023 年 1 月 31 日上午 10:00 UTC 至 2023 年 2 月 2 日上午 10:00 UTC 之間使用：

```
{
    "Statement": [
       {
            "Resource": "https://*",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.10/32"
                },
                "DateGreaterThan": {
                    "AWS:EpochTime": 1675159200
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1675332000
                }
            }
        }
    ]
}
```

您使用此政策的每個已簽署的 URL 都包括一個基本 URL，用於識別特定 CloudFront 分佈中的特定檔案，例如：

`https://d111111abcdef8.cloudfront.net/training/orientation.pdf`

該已簽署 URL 還包括金鑰對 ID，必須與在基本 URL 中指定的分佈 (d111111abcdef8.cloudfront.net) 中的可信金鑰群組相關聯。

## 為使用自訂準政策的已簽署 URL 建立簽章
<a name="private-content-custom-policy-creating-signature"></a>

使用自訂政策的已簽章的 URL 的簽章是政策聲明的雜湊、簽章和 base64-encoded 版本。若要建立自訂政策的簽章，請完成以下步驟。

如需有關如何對政策聲明進行雜湊、簽章和編碼的詳細資訊和範例，請參閱：
+ [用於 Base64 編碼和加密的 Linux 命令和 OpenSSL](private-content-linux-openssl.md)
+ [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)

**注意**  
連結的範例預設使用 SHA-1。若要改為使用 SHA-256，請在 OpenSSL 命令`sha256`中將 取代`sha1`為 ，並在簽章的 URL 中包含`Hash-Algorithm=SHA256`查詢參數。<a name="private-content-custom-policy-creating-signature-download-procedure"></a>

**選項 1：使用自訂政策建立簽章**

1. 使用 SHA-1 或 SHA-256 雜湊函數和產生的 RSA 或 ECDSA 私有金鑰來雜湊並簽署您在程序 中建立的 JSON 政策陳述式[為使用自訂政策的已簽章的 URL 建立政策聲明](#private-content-custom-policy-creating-policy-procedure)。使用不再包含空格但尚未進行 base64 編碼的政策陳述式版本。

   如果您使用 SHA-256，則必須在簽章的 URL `&Hash-Algorithm=SHA256`中包含 。

   對於雜湊函數所需的私有金鑰，使用其公有金鑰在活動的信任金鑰組中的私有金鑰進行分佈。
**注意**  
用於雜湊和簽名政策聲明的方法取決於您的程式設計語言和平台。如需程式碼範例，請參閱 [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)。

1. 從雜湊和已簽署字串中移除所有空格 (包括索引標籤和新行字元)。

1. 使用 MIME base64 編碼的 Base64-encode 字串。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html)

1. 在 `&Signature=` 之後，將結果值附加到已簽章的 URL，然後返回到[使用自訂政策建立簽章的 URL](#private-content-creating-signed-url-custom-policy-procedure)以完成已簽章的 URL 的各個部分的連接。

# 使用已簽署 Cookie
<a name="private-content-signed-cookies"></a>

當您不想變更目前 URL 或希望提供存取多個限制檔案 (例如，網站的訂閱者區域中的所有檔案) 時，CloudFront 簽署 Cookie 允許您控制那些可以存取您的內容的使用者。本主題說明使用已簽章的 Cookie 時的注意事項，並介紹如何使用標準和自訂政策設定已簽章的 Cookie。

**Topics**
+ [決定對已簽署 Cookie 使用標準或自訂政策](#private-content-choosing-canned-custom-cookies)
+ [已簽署 Cookie 的工作方式](#private-content-how-signed-cookies-work)
+ [防止濫用已簽署 Cookie](#private-content-signed-cookie-misuse)
+ [CloudFront 何時檢查已簽署 Cookie 中的到期日期和時間](#private-content-check-expiration-cookie)
+ [範例程式碼和第三方工具](#private-content-overview-sample-code-cookies)
+ [使用標準政策設定已簽署 Cookie](private-content-setting-signed-cookie-canned-policy.md)
+ [使用自訂政策設定已簽署 Cookie](private-content-setting-signed-cookie-custom-policy.md)
+ [使用 PHP 建立已簽署 Cookie](signed-cookies-PHP.md)

## 決定對已簽署 Cookie 使用標準或自訂政策
<a name="private-content-choosing-canned-custom-cookies"></a>

當您建立已簽章的 Cookie 時，您將編寫一個 JSON 格式的政策聲明來指定對已簽章的 Cookie 的限制，例如 Cookie 的有效時間。您可以使用標準政策或自訂政策。下表比較了標準和自訂政策：


****  

| 描述 | 標準政策 | 自訂政策 | 
| --- | --- | --- | 
| 您可以重複使用多個檔案的政策聲明。要重複使用政策聲明，您必須在 `Resource` 物件中使用萬用字元。如需詳細資訊，請參閱 [您在政策陳述式中為已簽章 Cookie 的自訂政策指定的值](private-content-setting-signed-cookie-custom-policy.md#private-content-custom-policy-statement-cookies-values))。 | 否 | 是 | 
| 您可以指定使用者可以開始存取您的內容的日期和時間 | 否 | 是 (選用) | 
| 您可以指定使用者無法再存取您的內容的日期和時間 | 是 | 是 | 
| 您可以指定可以存取您的內容的使用者的 IP 位址或 IP 位址範圍 | 否 | 是 (選用) | 

如需有關使用標準政策建立已簽章的 Cookie 的詳細資訊，請參閱 [使用標準政策設定已簽署 Cookie](private-content-setting-signed-cookie-canned-policy.md)。

如需有關使用自訂政策建立已簽章的 Cookie 的詳細資訊，請參閱 [使用自訂政策設定已簽署 Cookie](private-content-setting-signed-cookie-custom-policy.md)。

## 已簽署 Cookie 的工作方式
<a name="private-content-how-signed-cookies-work"></a>

以下概觀了如何為已簽署的 Cookie 設定 CloudFront，以及當使用者提交包含已簽署的 Cookie 的請求時，CloudFront 如何回應。

1. 在您的 CloudFront 分佈中，指定一或多個信任的金鑰群組，其中包含 CloudFront 可用來驗證 URL 簽章的公有金鑰。您可以使用對應的私有金鑰來簽署 URL。

   如需詳細資訊，請參閱 [指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。

1. 您開發應用程式，以判斷使用者是否應該存取您的內容，如果是，則向檢視器傳送三個 `Set-Cookie` 標頭。(每個 `Set-Cookie` 標頭只包含一個名稱值組，而 CloudFront 已簽署的 Cookie 需要三個名稱值組。) 在瀏覽者請求您的私有內容之前，您必須將 `Set-Cookie` 標頭傳送到檢視器。如果您在 Cookie 上設定了較短的到期時間，則可能還需要傳送三個 `Set-Cookie` 標頭以回應後續請求，以便使用者持續存取。

   一般而言，您的 CloudFront 分佈至少有兩個快取行為，一種不需要身分驗證，另一種需要驗證。網站安全部分的錯誤頁面包含重定向器或指向登入頁面的連結。

   如果您將分佈設定為根據 Cookie 的快取檔案，CloudFront 不會根據已簽署的 Cookie 中的屬性快取個別檔案。

1. 使用者登入您的網站，以及付費內容或滿足其他存取需求。

1. 您的應用程式傳回回應中的 `Set-Cookie` 標頭，並且檢視器會儲存名稱值組。

1. 使用者請求了檔案。

   使用者的瀏覽器或其他檢視器從步驟 4 取得名稱值組，並將它們新增至 `Cookie` 標頭中的請求中。這是已簽章的 Cookie。

1. CloudFront 使用公有金鑰來驗證已簽署的 Cookie 中的簽章，並確認該 Cookie 尚未遭到篡改。如果簽章無效，請求會遭到拒絕。

   如果 Cookie 中的簽章有效，CloudFront 將查看 Cookie 中的政策聲明 (或者如果使用的是標準政策，則建構一個聲明) 以確認請求仍然有效。例如，如果您為 Cookie 指定了開始和結束日期和時間，CloudFront 會確認使用者在您希望允許存取的時間段內嘗試存取您的內容。

   如果該請求符合政策聲明中的請求，則 CloudFront 將為您的內容提供服務，就像是不受限制的內容：它決定檔案是否已經在邊緣上快取，若需要，將請求轉傳到原始伺服器，並將該檔案傳回給使用者。

## 防止濫用已簽署 Cookie
<a name="private-content-signed-cookie-misuse"></a>

如果您在 `Domain` 標頭中指定 `Set-Cookie` 參數，請指定可能的最精確值，以降低具有相同根網域名稱之人員的存取可能性。例如，app.example.com 優於 example.com，尤其是當您無法控制 example.com 時。這有助於防止他人從 www.example.com 存取您的內容。

要協助避免發生這種類型的攻擊，請執行下列動作：
+ 排除 `Expires` 和 `Max-Age` 的屬性，以便 `Set-Cookie` 標頭建立工作階段 Cookie。工作階段 Cookie 會在使用者關閉瀏覽器時自動刪除，以降低有人未經授權存取您的內容的可能性。
+ 包含 `Secure` 屬性，以便檢視器在請求中包含該 Cookie 時，將對其進行加密。
+ 如果可能，請使用自訂政策，並包含檢視器的 IP 位址。
+ 在 `CloudFront-Expires` 屬性中，根據您希望使用者訪問您的內容的時間長度，指定最短的合理到期時間。

## CloudFront 何時檢查已簽署 Cookie 中的到期日期和時間
<a name="private-content-check-expiration-cookie"></a>

若要判斷已簽署的 Cookie 是否仍然有效，CloudFront 在 HTTP 請求時會檢查 Cookie 中的到期日期和時間。如果用戶端在到期前一刻才開始下載大型檔案，則即使在下載期間過期了，下載也應該要完成。如果 TCP 連線中斷並且用戶端在到期時間過後嘗試重新啟動下載，則下載將失敗。

如果用戶端使用範圍 GET 以取得較小型的檔案，則到期時間過後發生的任何 GET 請求都將失敗。如需範圍 GET 的詳細資訊，請參閱 [CloudFront 如何處理物件的部分請求 (範圍 GET)](RangeGETs.md)。

## 範例程式碼和第三方工具
<a name="private-content-overview-sample-code-cookies"></a>

私有內容的範本程式碼只說明如何為已簽章的 URL 建立簽章。但是，針對已簽章的 Cookie 建立簽章的程序非常類似，因此大部分範本程式碼仍然相關。如需詳細資訊，請參閱下列主題：
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 PHP 建立 URL 簽章](CreateURL_PHP.md)
+ [使用 C\$1 和 .NET 架構建立 URL 簽章](CreateSignatureInCSharp.md)
+ [使用 Java 建立 URL 簽章](CFPrivateDistJavaDevelopment.md)

# 使用標準政策設定已簽署 Cookie
<a name="private-content-setting-signed-cookie-canned-policy"></a>

若要使用標準政策設定已簽章的 Cookie，請完成以下步驟。若要建立簽章，請參閱 [為使用標準政策的已簽署 Cookie 建立簽章](#private-content-canned-policy-signature-cookies)。<a name="private-content-setting-signed-cookie-canned-policy-procedure"></a>

**使用標準政策設定已簽章的 Cookie**

1. 如果您使用 .NET 或 Java 建立已簽章的 Cookie，而且尚未將金鑰對的私有金鑰從預設的 .pem 格式重新格式化為與 .NET 或 Java 相容的格式，請現在執行此操作。如需詳細資訊，請參閱[重新格式化私有金鑰 (僅限 .NET 和 Java)](private-content-trusted-signers.md#private-content-reformatting-private-key)。

1. 將應用程式設定為傳送三個`Set-Cookie`標頭給核准的檢視器 （如果您想要指定雜湊演算法，則為四個）。您需要三個 `Set-Cookie` 標頭，因為每個 `Set-Cookie` 標頭只能包含一個名稱值組，而 CloudFront 已簽署的 Cookie 需要三個名稱值組。名稱值組是：`CloudFront-Expires`、`CloudFront-Signature` 和 `CloudFront-Key-Pair-Id`。您可以選擇包含第四個名稱值對 `CloudFront-Hash-Algorithm`，以指定用於簽章的雜湊演算法。在使用者對要控制存取的檔案發出第一次請求之前，這些值必須出現在檢視器。
**注意**  
一般而言，建議您排除 `Expires` 和 `Max-Age` 屬性。排除這些屬性會導致瀏覽器在使用者關閉瀏覽器時刪除 Cookie，從而降低有人未經授權存取您的內容的可能性。如需詳細資訊，請參閱[防止濫用已簽署 Cookie](private-content-signed-cookies.md#private-content-signed-cookie-misuse)。

   **Cookie 屬性的名稱區分大小寫**。

   只包含分行符號，以使屬性更易讀。

   ```
   Set-Cookie: 
   CloudFront-Expires=date and time in Unix time format (in seconds) and Coordinated Universal Time (UTC); 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   Set-Cookie: 
   CloudFront-Signature=hashed and signed version of the policy statement; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   Set-Cookie: 
   CloudFront-Key-Pair-Id=public key ID for the CloudFront public key whose corresponding private key you're using to generate the signature; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   Set-Cookie: 
   CloudFront-Hash-Algorithm=SHA1 or SHA256; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   ```  
**(選用) `Domain`**  
請求檔案的網域名稱。如果不指定 `Domain` 屬性，則預設值是 URL 中的網域名稱，並且它僅適用於指定的網域名稱，而不適用於子網域名稱。如果指定 `Domain` 屬性，它也適用於子網域名稱。網域名稱中的前導點 (例如 `Domain=.example.com`) 是可選的。此外，如果指定 `Domain` 屬性，則 URL 中的網域名稱和 `Domain` 屬性的值必須相符。  
您可以指定 CloudFront 指派給您的分佈的網域名稱，例如，d111111abcdef8.cloudfront.net，但不能為網域名稱指定 \$1.cloudfront.net。  
如果要在 URL 中使用備用網域名稱 (如 example.com)，則無論您是否指定了 `Domain` 屬性，都必須將備用網域名稱新增到分佈中。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [備用網域名稱 (CNAME)](DownloadDistValuesGeneral.md#DownloadDistValuesCNAME)。  
**(選用) `Path`**  
請求檔案的路徑。如果未指定 `Path` 屬性，則預設值為 URL 中的路徑。  
**`Secure`**  
在檢視器傳送請求之前，需要對 Cookie 進行加密。我們建議您透過 HTTPS 連線發送 `Set-Cookie` 標頭，以確保 Cookie 屬性免受中間人攻擊。  
**`HttpOnly`**  
定義瀏覽器 (在支援的情況下) 如何與 Cookie 值互動。使用 `HttpOnly` 時，JavaScript 無法存取 Cookie 值。此預防措施有助於緩解跨網站指令碼 (XSS) 攻擊。如需詳細資訊，請參閱[使用 HTTP cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)。  
**`CloudFront-Expires`**  
以 Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 指定過期日期和時間。例如，2026 年 1 月 1 日上午 10:00 UTC 以 Unix 時間格式轉換為 1767290400。  
若要使用 epoch 時間，請為不晚於 `9223372036854775807` 的日期指定 64 位元整數 (2262 年 4 月 11 日星期五 23:47:16.854 UTC)。  
如需世界協調時間的詳細資訊，請參閱 *RFC 3339、網際網路上的日期和時間：時間戳記*，[https://tools.ietf.org/html/rfc3339](https://tools.ietf.org/html/rfc3339)。  
**`CloudFront-Signature`**  
JSON 政策聲明的雜湊、簽章和 base64-encoded 版本。如需詳細資訊，請參閱 [為使用標準政策的已簽署 Cookie 建立簽章](#private-content-canned-policy-signature-cookies)。  
**`CloudFront-Key-Pair-Id`**  
CloudFront 公有金鑰的 ID，例如 `K2JCJMDEHXQW5F`。公有金鑰 ID 會告訴 CloudFront 要使用哪個公有金鑰來驗證已簽署的 URL。CloudFront 將簽章中的資訊與政策聲明中的資訊進行比較，以驗證該 URL 尚未遭到篡改。  
此公有金鑰必須屬於分佈中信任的簽署者金鑰群組。如需詳細資訊，請參閱[指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。  
**`CloudFront-Hash-Algorithm`**  
（選用） 用來建立簽章的雜湊演算法。支援的值為 `SHA1` 和 `SHA256`。如果您未包含此 Cookie，CloudFront 會預設為 `SHA1`。

以下範例顯示當您使用與檔案的 URL 中的分佈關聯的網域名稱時，一個已簽章的 Cookie 的 `Set-Cookie` 標頭：

```
Set-Cookie: CloudFront-Expires=1426500000; Domain=d111111abcdef8.cloudfront.net; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=yXrSIgyQoeE4FBI4eMKF6ho~CA8_; Domain=d111111abcdef8.cloudfront.net; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=d111111abcdef8.cloudfront.net; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=d111111abcdef8.cloudfront.net; Path=/images/*; Secure; HttpOnly
```

以下範例顯示當您在檔案的 URL 中使用備用網域名稱 example.org 時，一個已簽章的 Cookie 的 `Set-Cookie` 標頭：

```
Set-Cookie: CloudFront-Expires=1426500000; Domain=example.org; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=yXrSIgyQoeE4FBI4eMKF6ho~CA8_; Domain=example.org; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=example.org; Path=/images/*; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=example.org; Path=/images/*; Secure; HttpOnly
```

如果要在 URL 中使用備用網域名稱 (如 example.com)，則無論您是否指定了 `Domain` 屬性，都必須將備用網域名稱新增到分佈中。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [備用網域名稱 (CNAME)](DownloadDistValuesGeneral.md#DownloadDistValuesCNAME)。

## 為使用標準政策的已簽署 Cookie 建立簽章
<a name="private-content-canned-policy-signature-cookies"></a>

若要為使用標準政策的已簽署 Cookie 建立簽章，請完成下列程序。

**Topics**
+ [為使用標準政策的已簽署 Cookie 建立政策陳述式](#private-content-canned-policy-statement-cookies)
+ [簽署政策陳述式以為使用標準政策的已簽署 Cookie 建立簽章](#private-content-canned-policy-cookies-signing-policy-statement)

### 為使用標準政策的已簽署 Cookie 建立政策陳述式
<a name="private-content-canned-policy-statement-cookies"></a>

當您設定使用標準政策的簽章 Cookie 時，該 `CloudFront-Signature` 屬性是政策聲明的雜湊及已簽章的版本。對於使用標準政策的已簽章的 Cookie，您不會將政策聲明包括在 `Set-Cookie` 標頭中，就像使用自訂政策的已簽章的 Cookie 一樣。若要建立政策陳述式，請完成下列步驟。<a name="private-content-canned-policy-statement-cookies-procedure"></a>

**為使用標準政策的已簽章的 Cookie 建立政策聲明**

1. 建構政策聲明，使用下列 JSON 格式，並使用 UTF-8 字元編碼。完全按照規定包含所有標點符號和其他常值。如需有關 `Resource` 和 `DateLessThan` 參數的詳細資訊，請參閱 [您在政策陳述式中為已簽署 Cookie 標準政策所指定的值](#private-content-canned-policy-statement-cookies-values)。

   ```
   {
       "Statement": [
           {
               "Resource": "base URL or stream name",
               "Condition": {
                   "DateLessThan": {
                       "AWS:EpochTime": ending date and time in Unix time format and UTC
                   }
               }
           }
       ]
   }
   ```

1. 從政策陳述式中刪除所有空格 (包括標籤和新行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。

#### 您在政策陳述式中為已簽署 Cookie 標準政策所指定的值
<a name="private-content-canned-policy-statement-cookies-values"></a>

當您為標準政策建立政策聲明時，您可以指定以下值：

**資源**  
包含查詢字串的基本 URL (如果有)，例如：  
`https://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes`  
您只能為 `Resource` 指定一個值。  
注意下列事項：  
+ **通訊協定** – 此值必須以 `http://` 或 `https://` 開頭。
+ **查詢字串參數** – 如果沒有查詢字串參數，請省略問號。
+ **替代網域名稱** – 如果在 URL 中指定了替代網域名稱 (CNAME)，則在引用網頁或應用程式中的檔案時，必須指定替代網域名稱。請勿為檔案指定 Amazon S3 URL。

**DateLessThan**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的到期日期和時間。不要將值括在引號中。  
例如，2015 年 3 月 16 日上午 10:00 UTC 以 Unix 時間格式轉換為 1426500000。  
這個值必須符合 `CloudFront-Expires` 標頭中 `Set-Cookie` 屬性的值。不要將值括在引號中。  
如需詳細資訊，請參閱 [CloudFront 何時檢查已簽署 Cookie 中的到期日期和時間](private-content-signed-cookies.md#private-content-check-expiration-cookie)。

#### 標準政策的範例政策陳述式
<a name="private-content-canned-policy-cookies-sample-policy-statement"></a>

當您在已簽章的 Cookie 中使用以下範例政策聲明時，使用者在到 UTC 2015 年 3 月 16 日上午 10:00 之前可以存取檔案 `https://d111111abcdef8.cloudfront.net/horizon.jpg`：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/horizon.jpg?size=large&license=yes",
            "Condition": {
                "DateLessThan": {
                    "AWS:EpochTime": 1426500000
                }
            }
        }
    ]
}
```

### 簽署政策陳述式以為使用標準政策的已簽署 Cookie 建立簽章
<a name="private-content-canned-policy-cookies-signing-policy-statement"></a>

要為 `CloudFront-Signature` 標頭中的 `Set-Cookie` 屬性建立值，請對您在 [為使用標準政策的已簽章的 Cookie 建立政策聲明](#private-content-canned-policy-statement-cookies-procedure) 中建立的政策聲明進行雜湊和簽署。

如需有關如何對政策聲明進行雜湊、簽章和編碼的詳細資訊和範例，請參閱以下主題：
+ [用於 Base64 編碼和加密的 Linux 命令和 OpenSSL](private-content-linux-openssl.md)
+ [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)

**注意**  
連結的範例預設使用 SHA-1。若要改為使用 SHA-256，請在 OpenSSL 命令`sha256`中`sha1`將 取代為 ，並包含值為 的 `CloudFront-Hash-Algorithm` Cookie`SHA256`。<a name="private-content-canned-policy-cookie-creating-signature-procedure"></a>

**使用標準政策為已簽章的 Cookie 建立簽章**

1. 使用 SHA-1 或 SHA-256 雜湊函數和 RSA 來雜湊和簽署您在程序 中建立的政策陳述式[為使用標準政策的已簽章的 Cookie 建立政策聲明](#private-content-canned-policy-statement-cookies-procedure)。使用不再包含空格之政策陳述式的版本。

   如果您使用 SHA-256，則必須包含值為 的 `CloudFront-Hash-Algorithm` Cookie`SHA256`。

   對於雜湊函數所需的私有金鑰，使用其公有金鑰在活動的信任金鑰組中的私有金鑰進行分佈。
**注意**  
用於雜湊和簽名政策聲明的方法取決於您的程式設計語言和平台。如需程式碼範例，請參閱 [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)。

1. 從雜湊和已簽署字串中移除所有空格 (包括索引標籤和新行字元)。

1. 使用 MIME base64 編碼的 Base64-encode 字串。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-canned-policy.html)

1. 將結果值包含在 `Set-Cookie` 名稱值組的 `CloudFront-Signature` 標頭中。然後返回到 [使用標準政策設定已簽章的 Cookie](#private-content-setting-signed-cookie-canned-policy-procedure) 為 `Set-Cookie` 新增 `CloudFront-Key-Pair-Id` 標頭。

# 使用自訂政策設定已簽署 Cookie
<a name="private-content-setting-signed-cookie-custom-policy"></a>

若要設定使用標準政策的已簽署 Cookie，請完成以下步驟。<a name="private-content-setting-signed-cookie-custom-policy-procedure"></a>

**使用自訂政策設定已簽章的 Cookie**

1. 如果您使用 .NET 或 Java 建立簽章的 URL，並且您還沒有將金鑰對的私有金鑰從預設的 .pem 格式重新格式化為與 .NET 或 Java 相容的格式，則現在執行此操作。如需詳細資訊，請參閱[重新格式化私有金鑰 (僅限 .NET 和 Java)](private-content-trusted-signers.md#private-content-reformatting-private-key)。

1. 將應用程式設定為傳送三個`Set-Cookie`標頭給核准的檢視器 （如果您想要指定雜湊演算法，則為四個）。您需要三個 `Set-Cookie` 標頭，因為每個 `Set-Cookie` 標頭只能包含一個名稱值組，而 CloudFront 已簽署的 Cookie 需要三個名稱值組。名稱值組是：`CloudFront-Policy`、`CloudFront-Signature` 和 `CloudFront-Key-Pair-Id`。您可以選擇包含第四個名稱值對 `CloudFront-Hash-Algorithm`，以指定用於簽章的雜湊演算法。在使用者對要控制存取的檔案發出第一次請求之前，這些值必須出現在檢視器。
**注意**  
一般而言，建議您排除 `Expires` 和 `Max-Age` 屬性。這會導致瀏覽器在使用者關閉瀏覽器時刪除 Cookie，從而降低有人未經授權存取您的內容的可能性。如需詳細資訊，請參閱 [防止濫用已簽署 Cookie](private-content-signed-cookies.md#private-content-signed-cookie-misuse)。

   **Cookie 屬性的名稱區分大小寫**。

   只包含分行符號，以使屬性更易讀。

   ```
   Set-Cookie: 
   CloudFront-Policy=base64 encoded version of the policy statement; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   
   Set-Cookie: 
   CloudFront-Signature=hashed and signed version of the policy statement; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   Set-Cookie: 
   CloudFront-Key-Pair-Id=public key ID for the CloudFront public key whose corresponding private key you're using to generate the signature; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   
   Set-Cookie: 
   CloudFront-Hash-Algorithm=SHA1 or SHA256; 
   Domain=optional domain name; 
   Path=/optional directory path; 
   Secure; 
   HttpOnly
   ```  
**(選用) `Domain`**  
請求檔案的網域名稱。如果不指定 `Domain` 屬性，則預設值是 URL 中的網域名稱，並且它僅適用於指定的網域名稱，而不適用於子網域名稱。如果指定 `Domain` 屬性，它也適用於子網域名稱。網域名稱中的前導點 (例如 `Domain=.example.com`) 是可選的。此外，如果指定 `Domain` 屬性，則 URL 中的網域名稱和 `Domain` 屬性的值必須相符。  
您可以指定 CloudFront 指派給您的分佈的網域名稱，例如，d111111abcdef8.cloudfront.net，但不能為網域名稱指定 \$1.cloudfront.net。  
如果要在 URL 中使用備用網域名稱 (如 example.com)，則無論您是否指定了 `Domain` 屬性，都必須將備用網域名稱新增到分佈中。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [備用網域名稱 (CNAME)](DownloadDistValuesGeneral.md#DownloadDistValuesCNAME)。  
**(選用) `Path`**  
請求檔案的路徑。如果未指定 `Path` 屬性，則預設值為 URL 中的路徑。  
**`Secure`**  
在檢視器傳送請求之前，需要對 Cookie 進行加密。我們建議您透過 HTTPS 連線發送 `Set-Cookie` 標頭，以確保 Cookie 屬性免受中間人攻擊。  
**`HttpOnly`**  
要求檢視器僅在 HTTP 或 HTTPS 請求中傳送 Cookie。  
**`CloudFront-Policy`**  
您的政策陳述式採用 JSON 格式，刪除了空格，然後使用 base64 編碼。如需詳細資訊，請參閱[為使用自訂政策的已簽署 Cookie 建立簽章](#private-content-custom-policy-signature-cookies)。  
政策陳述式可控制已簽署 Cookie 授予使用者的存取權限。它包括使用者可以存取的檔案、到期日期和時間、URL 變成有效的選擇性日期和時間，以及允許存取檔案的選用 IP 位址或 IP 位址範圍。  
**`CloudFront-Signature`**  
JSON 政策聲明的雜湊、簽章和 base64-encoded 版本。如需詳細資訊，請參閱 [為使用自訂政策的已簽署 Cookie 建立簽章](#private-content-custom-policy-signature-cookies)。  
**`CloudFront-Key-Pair-Id`**  
CloudFront 公有金鑰的 ID，例如 `K2JCJMDEHXQW5F`。公有金鑰 ID 會告訴 CloudFront 要使用哪個公有金鑰來驗證已簽署的 URL。CloudFront 將簽章中的資訊與政策聲明中的資訊進行比較，以驗證該 URL 尚未遭到篡改。  
此公有金鑰必須屬於分佈中信任的簽署者金鑰群組。如需詳細資訊，請參閱[指定可以建立已簽署 URL 和已簽署 Cookie 的簽署者](private-content-trusted-signers.md)。  
**`CloudFront-Hash-Algorithm`**  
（選用） 用來建立簽章的雜湊演算法。支援的值為 `SHA1` 和 `SHA256`。如果您未包含此 Cookie，CloudFront 會預設為 `SHA1`。

## 自訂政策的 `Set-Cookie` 標頭範例
<a name="example-set-cookie-headers-custom-policy"></a>

請參閱下列 `Set-Cookie` 標頭對的範例。

如果要在 URL 中使用備用網域名稱 (如 example.org)，則無論您是否指定了 `Domain` 屬性，都必須將備用網域名稱新增到分佈中。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [備用網域名稱 (CNAME)](DownloadDistValuesGeneral.md#DownloadDistValuesCNAME)。

**Example 範例 1**  
當您使用與檔案的 URL 中的分佈關聯的網域名稱時，可以使用一個已簽署 Cookie 的 `Set-Cookie` 標頭。  

```
Set-Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=dtKhpJ3aUYxqDIwepczPiDb9NXQ_; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
```

**Example 範例 2**  
當您在檔案的 URL 中使用備用網域名稱 (example.org) 時，可以使用一個已簽署 Cookie 的 `Set-Cookie` 標頭。  

```
Set-Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=dtKhpJ3aUYxqDIwepczPiDb9NXQ_; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=example.org; Path=/; Secure; HttpOnly
```

**Example 範例 3**  
當您使用與檔案的 URL 中的分佈關聯的網域名稱時，可以使用一個已簽署請求的 `Set-Cookie` 標頭對。  

```
Set-Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=dtKhpJ3aUYxqDIwepczPiDb9NXQ_; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=dd111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly
```

**Example 範例 4**  
當您使用與檔案的 URL 中的分佈關聯的替代網域名稱 (example.org) 時，可以使用一個已簽署請求的 `Set-Cookie` 標頭對。  

```
Set-Cookie: CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Signature=dtKhpJ3aUYxqDIwepczPiDb9NXQ_; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Key-Pair-Id=K2JCJMDEHXQW5F; Domain=example.org; Path=/; Secure; HttpOnly
Set-Cookie: CloudFront-Hash-Algorithm=SHA256; Domain=example.org; Path=/; Secure; HttpOnly
```

## 為使用自訂政策的已簽署 Cookie 建立政策陳述式
<a name="private-content-custom-policy-statement-cookies"></a>

若要為自訂政策建立政策陳述式，請執行以下步驟。如需以各種方式控制對檔案存取的幾個政策聲明範例，請參閱 [使用自訂政策的已簽署 Cookie 範例政策陳述式](#private-content-custom-policy-statement-signed-cookies-examples)。<a name="private-content-custom-policy-statement-cookies-procedure"></a>

**為使用自訂政策的簽章的 Cookie 建立政策聲明**

1. 使用下列 JSON 格式建構政策聲明。

   ```
   {
       "Statement": [
           {
               "Resource": "URL of the file",
               "Condition": {
                   "DateLessThan": {
                       "AWS:EpochTime":required ending date and time in Unix time format and UTC
                   },
                   "DateGreaterThan": {
                       "AWS:EpochTime":optional beginning date and time in Unix time format and UTC
                   },
                   "IpAddress": {
                       "AWS:SourceIp": "optional IP address"
                   }
               }
           }
       ]
   }
   ```

   注意下列事項：
   + 您只能包含一個聲明。
   + 使用 UTF-8 字元編碼。
   + 完全按照規定包含所有標點符號和參數名稱。不接受參數名稱的縮寫。
   + `Condition` 部分的參數順序不重要。
   + 如需有關 `Resource`、`DateLessThan`、`DateGreaterThan` 和 `IpAddress` 值的詳細資訊，請參閱 [您在政策陳述式中為已簽章 Cookie 的自訂政策指定的值](#private-content-custom-policy-statement-cookies-values)。

1. 從政策陳述式中刪除所有空格 (包括標籤和新行字元)。您可能必須在應用程式的程式碼的字串中包含逸出字元。

1. 使用 MIME base64 編碼 Base64-encode 政策聲明。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html)

1. 將結果值包含在您的 `Set-Cookie` 標頭後的 `CloudFront-Policy=`。

1. 透過進行雜湊、簽章和 base64 編碼政策聲明來為 `Set-Cookie` 建立`CloudFront-Signature` 標頭的簽章。如需詳細資訊，請參閱 [為使用自訂政策的已簽署 Cookie 建立簽章](#private-content-custom-policy-signature-cookies)。

### 您在政策陳述式中為已簽章 Cookie 的自訂政策指定的值
<a name="private-content-custom-policy-statement-cookies-values"></a>

當您為自訂政策建立政策聲明時，您可以指定以下值。

**資源**  
包含查詢字串的基本 URL (如果有)：  
`https://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes`  
如果省略 `Resource` 參數，則使用者可以存取與用於建立已簽章的 URL 的金鑰對相關聯的任何分佈的所有檔案。
您只能為 `Resource` 指定一個值。  
注意下列事項：  
+ **通訊協定** – 此值必須以 `http://` 或 `https://` 開頭。
+ **查詢字串參數** – 如果沒有查詢字串參數，請省略問號。
+ **萬用字元** – 可以使用比對零或多個字元 (\$1) 的萬用字元，或比對字串中任意位置單一字元 (?) 的萬用字元。例如，值為：

  `https://d111111abcdef8.cloudfront.net/*game_download.zip*`

  將包括 (例如) 下列檔案：
  + `https://d111111abcdef8.cloudfront.net/game_download.zip`
  + `https://d111111abcdef8.cloudfront.net/example_game_download.zip?license=yes`
  + `https://d111111abcdef8.cloudfront.net/test_game_download.zip?license=temp`
+ **替代網域名稱** – 如果在 URL 中指定了替代網域名稱 (CNAME)，則在引用網頁或應用程式中的檔案時，必須指定替代網域名稱。請勿為檔案指定 Amazon S3 URL。

**DateLessThan**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的到期日期和時間。不要將值括在引號中。  
例如，2015 年 3 月 16 日上午 10:00 UTC 以 Unix 時間格式轉換為 1426500000。  
如需詳細資訊，請參閱 [CloudFront 何時檢查已簽署 Cookie 中的到期日期和時間](private-content-signed-cookies.md#private-content-check-expiration-cookie)。

**DateGreaterThan (選用)**  
Unix 時間格式 (以秒為單位) 和國際標準時間 (UTC) 的 URL 的選用日期和時間。不允許使用者在指定的日期和時間之前存取檔案。不要將值括在引號中。

**IpAddress (選用)**  
提出 GET 請求的用戶端 IP 位址。注意下列事項：  
+ 要允許任何 IP 位址存取該檔案，請省略 `IpAddress` 參數。
+ 您可以指定一個 IP 位址或一個 IP 位址範圍。例如，如果用戶端的 IP 位址位於兩個不同的範圍之一，則無法設定政策以允許存取。
+ 若要允許從單一 IP 位址存取，您需要指定：

  `"`*IPv4 IP 位址*`/32"`
+ 必須以標準 IPv4 CIDR 格式指定 IP 位址範圍 (例如 `192.0.2.0/24`)。如需詳細資訊，請前往 *RFC 4632，無類別網域間路由選擇 (CIDR)：網際網路地址指派和彙總計劃*，[https://tools.ietf.org/html/rfc4632](https://tools.ietf.org/html/rfc4632)。
**重要**  
不支援 IPv6 格式的 IP 位址，例如 2001:0db8:85a3::8a2e:0370:7334。

  如果您使用的是包括 `IpAddress` 的自訂政策，請不要為分佈啟用 IPv6。如果您希望透過 IP 位址限制對某些內容的存取，並支援對其他內容的 IPv6 請求，則可以建立兩個分佈。如需詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md) 主題中的 [啟用 IPv6 (檢視器請求)](DownloadDistValuesGeneral.md#DownloadDistValuesEnableIPv6)。

## 使用自訂政策的已簽署 Cookie 範例政策陳述式
<a name="private-content-custom-policy-statement-signed-cookies-examples"></a>

以下範例說明政策聲明說明了如何控制對特定檔案的存取、目錄中的所有檔案，或與金鑰對 ID 相關聯的所有檔案。此範例還會說明如何控制來自個別的 IP 位址或各種 IP 位址的存取，以及如何防止使用者在指定的日期和時間之後使用已簽章的 Cookie。

如果複製並貼上這些範例中的任何一項，請刪除所有空格 (包括索引標籤和換行符號字元)、用您自我的值取代該值，並在大括弧 ( \$1 ) 的後面加上換行字元。

如需詳細資訊，請參閱[您在政策陳述式中為已簽章 Cookie 的自訂政策指定的值](#private-content-custom-policy-statement-cookies-values)。

**Topics**
+ [範例政策陳述式：從一個 IP 位址範圍存取一個檔案](#private-content-custom-policy-statement-signed-cookies-example-one-object)
+ [範例政策陳述式：從一個 IP 位址範圍存取目錄中的所有檔案](#private-content-custom-policy-statement-signed-cookies-example-all-objects)
+ [範例政策陳述式：從一個 IP 位址存取與金鑰對 ID 相關的所有檔案](#private-content-custom-policy-statement-signed-cookies-example-one-ip)

### 範例政策陳述式：從一個 IP 位址範圍存取一個檔案
<a name="private-content-custom-policy-statement-signed-cookies-example-one-object"></a>

以下範例自訂政策在已簽署的 Cookie 中，其指定使用者在 2023 年 1 月 1 日上午 10:00 (UTC) 之前，可以從 `192.0.2.0/24` 範圍內的 IP 位址存取檔案 `https://d111111abcdef8.cloudfront.net/game_download.zip`：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/game_download.zip",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.0/24"
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1767290400
                }
            }
        }
    ]
}
```

### 範例政策陳述式：從一個 IP 位址範圍存取目錄中的所有檔案
<a name="private-content-custom-policy-statement-signed-cookies-example-all-objects"></a>

以下範例自訂政策允許您為 `training` 目錄中的任何檔案建立已簽章的 Cookie，如 `Resource` 參數中的 \$1 萬用字元所示。使用者在到 UTC 2013 年 1 月 1 日上午 10:00 之前可以從 `192.0.2.0/24` 範圍內的 IP 位址存取該檔案：

```
{
    "Statement": [
        {
            "Resource": "https://d111111abcdef8.cloudfront.net/training/*",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.0/24"
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1767290400
                }
            }
        }
    ]
}
```

您使用此政策的每個已簽章的 Cookie 都包括一個識別特定的檔案的基本 URL，例如：

`https://d111111abcdef8.cloudfront.net/training/orientation.pdf`

### 範例政策陳述式：從一個 IP 位址存取與金鑰對 ID 相關的所有檔案
<a name="private-content-custom-policy-statement-signed-cookies-example-one-ip"></a>

以下範例自訂政策允許您為與任何分佈關聯的任何檔案設定已簽章的 Cookie，如 `Resource` 參數中的 \$1 萬用字元所示。使用者必須使用 IP 位址 `192.0.2.10/32`。(CIDR 表示法中的 `192.0.2.10/32` 值是指單個 IP 位址 `192.0.2.10`。) 這些檔案只能在 2013 年 1 月 1 日上午 10:00 UTC 至 2013 年 1 月 2 日上午 10:00 UTC 之間可用：

```
{
    "Statement": [
        {
            "Resource": "https://*",
            "Condition": {
                "IpAddress": {
                    "AWS:SourceIp": "192.0.2.10/32"
                },
                "DateGreaterThan": {
                    "AWS:EpochTime": 1767290400
                },
                "DateLessThan": {
                    "AWS:EpochTime": 1767376800
                }
            }
        }
    ]
}
```

您使用此政策的每個已簽署的 Cookie 都包括一個基本 URL，用於識別特定 CloudFront 分佈中的特定檔案，例如：

`https://d111111abcdef8.cloudfront.net/training/orientation.pdf`

該已簽署 Cookie 還包括金鑰對 ID，必須與在基本 URL 中指定的分佈 (d111111abcdef8.cloudfront.net) 內信任的簽署者相關聯。

## 為使用自訂政策的已簽署 Cookie 建立簽章
<a name="private-content-custom-policy-signature-cookies"></a>

使用自訂政策的已簽章的 Cookie 的簽章是政策聲明的雜湊、簽章和 base64-encoded 版本。

如需有關如何對政策聲明進行雜湊、簽章和編碼的詳細資訊和範例，請參閱：
+ [用於 Base64 編碼和加密的 Linux 命令和 OpenSSL](private-content-linux-openssl.md)
+ [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)

**注意**  
連結的範例預設使用 SHA-1。若要改為使用 SHA-256，請在 OpenSSL 命令`sha256`中`sha1`將 取代為 ，並包含值為 的 `CloudFront-Hash-Algorithm` Cookie`SHA256`。<a name="private-content-custom-policy-signature-cookies-procedure"></a>

**使用自訂政策為已簽章的 Cookie 建立簽章**

1. 使用 SHA-1 或 SHA-256 雜湊函數和 RSA 來雜湊和簽署您在程序 中建立的 JSON 政策陳述式[為使用自訂政策的已簽章的 URL 建立政策聲明](private-content-creating-signed-url-custom-policy.md#private-content-custom-policy-creating-policy-procedure)。使用不再包含空格但尚未進行 base64 編碼的政策陳述式版本。

   如果您使用 SHA-256，則必須包含值為 的 `CloudFront-Hash-Algorithm` Cookie`SHA256`。

   對於雜湊函數所需的私有金鑰，使用其公有金鑰在活動的信任金鑰組中的私有金鑰進行分佈。
**注意**  
用於雜湊和簽名政策聲明的方法取決於您的程式設計語言和平台。如需程式碼範例，請參閱 [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)。

1. 從雜湊和已簽署字串中移除所有空格 (包括索引標籤和新行字元)。

1. 使用 MIME base64 編碼的 Base64-encode 字串。如需詳細資訊，請參閱 *RFC 2045，MIME (多用途網際網路郵件延伸) 第一部分：網際網路訊息內文的格式*中的[第 6.8 節：Base64 Content-Transfer-Encoding](https://tools.ietf.org/html/rfc2045#section-6.8)。

1. 將 URL 查詢字串中無效的字元替換為有效的字元。下表列出無效和有效的字元。  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html)

1. 將結果值包含在 `Set-Cookie` 名稱值組的 `CloudFront-Signature=` 標頭中，並返回到 [使用自訂政策設定已簽章的 Cookie](#private-content-setting-signed-cookie-custom-policy-procedure) 為 `Set-Cookie` 新增 `CloudFront-Key-Pair-Id` 標頭。

# 使用 PHP 建立已簽署 Cookie
<a name="signed-cookies-PHP"></a>

下列程式碼範例類似於 [使用 PHP 建立 URL 簽章](CreateURL_PHP.md) 中建立影片連結的範例。不過，此範例不會在程式碼中簽署 URL，而是使用 `create_signed_cookies()` 函數簽署 Cookie。用戶端播放器使用 Cookie 對 CloudFront 分佈的每個請求進行身分驗證。

此方法有助於串流內容，例如 HTTP Live Streaming (HLS) 或透過 HTTP 的動態自適應串流 (DASH)，其中用戶端需要提出多個請求來擷取資訊清單、區段和相關播放資產。透過使用簽署的 Cookie，用戶端可以驗證每個請求，而不需要為每個區段產生新的已簽署 URL。

**注意**  
建立 URL 簽章只是私有內容提供服務的程序的一部分，以使用已簽署 Cookie。如需詳細資訊，請參閱[使用已簽署 Cookie](private-content-signed-cookies.md)。



**Topics**
+ [建立 RSA SHA-1 或 SHA-256 簽章](#create-rsa-sha-1signature-cookies)
+ [建立已簽署 Cookie](#create-the-signed-cookie)
+ [完整程式碼](#full-code-signed-cookies)

下列各節將程式碼範例細分為個別部分。您可以在下面找到完整的[程式碼範例](#full-code-signed-cookies)。

## 建立 RSA SHA-1 或 SHA-256 簽章
<a name="create-rsa-sha-1signature-cookies"></a>

此程式碼會執行下列操作：

1. 函數會使用 SHA-1 雜`rsa_sha1_sign`湊並簽署政策陳述式。若要改用 SHA-256，請使用如下所示的 rsa\$1sha256\$1sign 函數。所需的引數為政策陳述式，以及與您分佈之信任金鑰群組中公有金鑰對應的私有金鑰。

1. 接著，該 `url_safe_base64_encode` 函數會建立已簽章的 URL 安全版本。

   ```
   function rsa_sha1_sign($policy, $private_key_filename) {
       $signature = "";
       $fp = fopen($private_key_filename, "r");
       $priv_key = fread($fp, 8192);
       fclose($fp);
       $pkeyid = openssl_get_privatekey($priv_key);
       openssl_sign($policy, $signature, $pkeyid);
       openssl_free_key($pkeyid);
       return $signature;
   }
   
   function url_safe_base64_encode($value) {
       $encoded = base64_encode($value);
       return str_replace(
           array('+', '=', '/'),
           array('-', '_', '~'),
           $encoded);
   }
   ```

   下列函數使用 SHA-256 而非 SHA-1：

   ```
   function rsa_sha256_sign($policy, $private_key_filename) {
       $signature = "";
       $fp = fopen($private_key_filename, "r");
       $priv_key = fread($fp, 8192);
       fclose($fp);
       $pkeyid = openssl_get_privatekey($priv_key);
       openssl_sign($policy, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
       openssl_free_key($pkeyid);
       return $signature;
   }
   ```

   `rsa_sha256_sign` 函數與 相同`rsa_sha1_sign`，但會傳遞`OPENSSL_ALGO_SHA256`給 `openssl_sign`。當您使用 SHA-256 時，請包含值為 的 `CloudFront-Hash-Algorithm` Cookie`SHA256`。

## 建立已簽署 Cookie
<a name="create-the-signed-cookie"></a>

下列程式碼會使用下列 Cookie 屬性來建構 建立簽章的 Cookie：`CloudFront-Expires`、 `CloudFront-Signature``CloudFront-Key-Pair-Id`和 `CloudFront-Hash-Algorithm`。程式碼使用自訂政策。

```
function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null, $hash_algorithm = 'SHA1') {
    $policy = array(
        'Statement' => array(
            array(
                'Resource' => $resource,
                'Condition' => array(
                    'DateLessThan' => array('AWS:EpochTime' => $expires)
                )
            )
        )
    );

    if ($client_ip) {
        $policy['Statement'][0]['Condition']['IpAddress'] = array('AWS:SourceIp' => $client_ip . '/32');
    }

    $policy = json_encode($policy);
    $encoded_policy = url_safe_base64_encode($policy);
    if ($hash_algorithm === 'SHA256') {
        $signature = rsa_sha256_sign($policy, $private_key_filename);
    } else {
        $signature = rsa_sha1_sign($policy, $private_key_filename);
    }
    $encoded_signature = url_safe_base64_encode($signature);

    $cookies = array(
        'CloudFront-Policy' => $encoded_policy,
        'CloudFront-Signature' => $encoded_signature,
        'CloudFront-Key-Pair-Id' => $key_pair_id
    );

    if ($hash_algorithm === 'SHA256') {
        $cookies['CloudFront-Hash-Algorithm'] = 'SHA256';
    }

    return $cookies;
}
```

如需詳細資訊，請參閱[使用自訂政策設定已簽署 Cookie](private-content-setting-signed-cookie-custom-policy.md)。

## 完整程式碼
<a name="full-code-signed-cookies"></a>

下面的範例程式碼提供了使用 PHP 建立 CloudFront 已簽署 Cookie 的完整示範。您可以從 [demo-php.zip](samples/demo-php.zip) 檔案下載完整範例。

您可以在下列範例中修改 `$policy Condition` 元素，以允許 IPv4 與 IPv6 位址範圍。如需範例，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[在 IAM 政策中使用 IPv6 位址](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ipv6-access.html#ipv6-access-iam)。

```
<?php

function rsa_sha1_sign($policy, $private_key_filename) {
    $signature = "";
    $fp = fopen($private_key_filename, "r");
    $priv_key = fread($fp, 8192);
    fclose($fp);
    $pkeyid = openssl_get_privatekey($priv_key);
    openssl_sign($policy, $signature, $pkeyid);
    openssl_free_key($pkeyid);
    return $signature;
}

function url_safe_base64_encode($value) {
    $encoded = base64_encode($value);
    return str_replace(
        array('+', '=', '/'),
        array('-', '_', '~'),
        $encoded);
}

function rsa_sha256_sign($policy, $private_key_filename) {
    $signature = "";
    $fp = fopen($private_key_filename, "r");
    $priv_key = fread($fp, 8192);
    fclose($fp);
    $pkeyid = openssl_get_privatekey($priv_key);
    openssl_sign($policy, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
    openssl_free_key($pkeyid);
    return $signature;
}

function create_signed_cookies($resource, $private_key_filename, $key_pair_id, $expires, $client_ip = null, $hash_algorithm = 'SHA1') {
    $policy = array(
        'Statement' => array(
            array(
                'Resource' => $resource,
                'Condition' => array(
                    'DateLessThan' => array('AWS:EpochTime' => $expires)
                )
            )
        )
    );

    if ($client_ip) {
        $policy['Statement'][0]['Condition']['IpAddress'] = array('AWS:SourceIp' => $client_ip . '/32');
    }

    $policy = json_encode($policy);
    $encoded_policy = url_safe_base64_encode($policy);
    if ($hash_algorithm === 'SHA256') {
        $signature = rsa_sha256_sign($policy, $private_key_filename);
    } else {
        $signature = rsa_sha1_sign($policy, $private_key_filename);
    }
    $encoded_signature = url_safe_base64_encode($signature);

    $cookies = array(
        'CloudFront-Policy' => $encoded_policy,
        'CloudFront-Signature' => $encoded_signature,
        'CloudFront-Key-Pair-Id' => $key_pair_id
    );

    if ($hash_algorithm === 'SHA256') {
        $cookies['CloudFront-Hash-Algorithm'] = 'SHA256';
    }

    return $cookies;
}



$private_key_filename = '/home/test/secure/example-priv-key.pem';
$key_pair_id = 'K2JCJMDEHXQW5F';
$base_url = 'https://d1234.cloudfront.net';

$expires = time() + 3600; // 1 hour from now

// Get the viewer real IP from the x-forward-for header as $_SERVER['REMOTE_ADDR'] will return viewer facing IP. An alternative option is to use CloudFront-Viewer-Address header. Note that this header is a trusted CloudFront immutable header. Example format: IP:PORT ("CloudFront-Viewer-Address": "1.2.3.4:12345")
$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];


// For HLS manifest and segments (using wildcard)
$hls_resource = $base_url . '/sign/*';
$signed_cookies = create_signed_cookies($hls_resource, $private_key_filename, $key_pair_id, $expires, $client_ip, 'SHA256');

// Set the cookies
$cookie_domain = parse_url($base_url, PHP_URL_HOST);
foreach ($signed_cookies as $name => $value) {
    setcookie($name, $value, $expires, '/', $cookie_domain, true, true);
}

?>

<!DOCTYPE html>
<html>
<head>
    <title>CloudFront Signed HLS Stream with Cookies</title>
</head>
<body>
    <h1>Amazon CloudFront Signed HLS Stream with Cookies</h1>
    <h2>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?> only viewable by IP <?php echo $client_ip; ?></h2>
    
    <div id='hls-video'>
        <video id="video" width="640" height="360" controls></video>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <script>
        var video = document.getElementById('video');
        var manifestUrl = '<?php echo $base_url; ?>/sign/manifest.m3u8';
        
        if (Hls.isSupported()) {
            var hls = new Hls();
            hls.loadSource(manifestUrl);
            hls.attachMedia(video);
        }
        else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = manifestUrl;
        }
    </script>
</body>
</html>
```

您可以使用已簽署 URL，而不是使用已簽署 Cookie。如需詳細資訊，請參閱[使用 PHP 建立 URL 簽章](CreateURL_PHP.md)。

# 用於 Base64 編碼和加密的 Linux 命令和 OpenSSL
<a name="private-content-linux-openssl"></a>

您可以使用以下 Linux 命令列命令和 OpenSSL 來雜湊和簽署政策聲明、base64 編碼簽章，並將 URL 查詢字串參數中無效的字元替換為有效的字元。

如需 OpenSSL 的詳細資訊，請前往 [https://www.openssl.org](https://www.openssl.org)。

SHA-1 （預設）：

```
cat policy | tr -d "\n" | tr -d " \t\n\r" | openssl sha1 -sign private_key.pem | openssl base64 -A | tr -- '+=/' '-_~'
```

SHA-256：

```
cat policy | tr -d "\n" | tr -d " \t\n\r" | openssl sha256 -sign private_key.pem | openssl base64 -A | tr -- '+=/' '-_~'
```

在上述命令中：
+ `cat` 會讀取 `policy` 檔案。
+ `tr -d "\n" | tr -d " \t\n\r"` 會移除 `cat` 所新增的空格和新行字元。
+ OpenSSL 會使用 SHA-1 （或 SHA-256) 雜湊檔案，並使用私有金鑰檔案 簽署該檔案`private_key.pem`。私有金鑰簽章可以是 RSA 2048 或 ECDSA 256。如果您使用 SHA-256，請在已簽章的 URL 中包含`Hash-Algorithm=SHA256`查詢參數，或在已簽章的 `CloudFront-Hash-Algorithm=SHA256` Cookie 中包含 Cookie。
+ 使用 OpenSSL base64 來將經過雜湊演算和簽署的政策陳述式編碼。
+ `tr` 以有效字元取代 URL 查詢字串參數中無效的字元。

如需示範建立簽章的更多程式碼範例，請參閱 [為已簽署 URL 建立簽章的程式碼範例](PrivateCFSignatureCodeAndExamples.md)。

# 為已簽署 URL 建立簽章的程式碼範例
<a name="PrivateCFSignatureCodeAndExamples"></a>

本節包含可下載的應用程式範例，示範如何為已簽章的 URL 建立簽章。範例可在 Perl、PHP、C\$1 和 Java 中找到。您可以使用任何範例來建立簽章的 URL。Perl 指令碼在 Linux 和 macOS 平台上執行。PHP 範例可以在任何執行 PHP 的伺服器上執行。C\$1 範例使用 .NET 架構。

本節中的範例使用 SHA-1 來雜湊和簽署政策陳述式。您也可以使用 SHA-256。若要使用 SHA-256，請在簽署函數中更新雜湊演算法 （例如，在 OpenSSL 呼叫`sha256`中`sha1`將 取代為 ，或在語言的密碼編譯程式庫中使用同等的 SHA-256 常數）。當您使用 SHA-256 時，請在簽章的 URL 中包含`Hash-Algorithm=SHA256`查詢參數。

如需 JavaScript (Node.js) 中的範例程式碼，請參閱 AWS 開發人員部落格上的在 [Node.js 中建立 Amazon CloudFront 簽章 URLs](https://aws.amazon.com/blogs/developer/creating-amazon-cloudfront-signed-urls-in-node-js/)。

例如 Python 中的程式碼，請參閱《*適用於 Python (Boto3) 的AWS SDK API 參考》*中的[為 Amazon CloudFront 產生簽署的 URL](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudfront.html#examples)，以及 Boto3 GitHub 儲存庫中的[此範例程式碼](https://github.com/boto/boto3/blob/develop/boto3/examples/cloudfront.rst)。

**Topics**
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 PHP 建立 URL 簽章](CreateURL_PHP.md)
+ [使用 C\$1 和 .NET 架構建立 URL 簽章](CreateSignatureInCSharp.md)
+ [使用 Java 建立 URL 簽章](CFPrivateDistJavaDevelopment.md)

# 使用 Perl 建立 URL 簽章
<a name="CreateURLPerl"></a>

本節包含適用於 Linux/Mac 平台的 Perl 指令碼，可用來建立私有內容的簽章。若要建立簽章，請使用命令列參數指定 CloudFront URL、簽署者的私有金鑰路徑、金鑰 ID 和 URL 的過期日期，來執行指令碼。此工具也可以解碼簽章的 URL。

**備註**  
建立 URL 簽章只是私有內容提供服務的程序的一部分，以使用簽章 URL。如需端對端程序的詳細資訊，請參閱 [使用已簽署 URL](private-content-signed-urls.md)。
在簽署命令中，請注意 `sha1`可以在 `openssl dgst` 呼叫`sha256`中取代為 。

**Topics**
+ [用於建立已簽署 URL 的 Perl 指令碼來源](#CreateURLPerlScriptSource)

## 用於建立已簽署 URL 的 Perl 指令碼來源
<a name="CreateURLPerlScriptSource"></a>

以下 Perl 原始程式碼可用來建立適用於 CloudFront 簽章的 URL。程式碼中的註解包含有關命令列參數和工具功能的詳細資訊。

```
#!/usr/bin/perl -w

# Copyright 2008 Amazon Technologies, Inc.  Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may obtain a copy of the License at:
#
# https://aws.amazon.com/apache2.0
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under the License.

=head1 cfsign.pl

cfsign.pl - A tool to generate and verify Amazon CloudFront signed URLs

=head1 SYNOPSIS

This script uses an existing RSA key pair to sign and verify Amazon CloudFront signed URLs

View the script source for details as to which CPAN packages are required beforehand. 

For help, try:

cfsign.pl --help

URL signing examples:

cfsign.pl --action encode --url https://images.my-website.com/gallery1.zip --policy sample_policy.json --private-key privkey.pem --key-pair-id mykey

cfsign.pl --action encode --url https://images.my-website.com/gallery1.zip --expires 1257439868 --private-key privkey.pem --key-pair-id mykey

URL decode example:

cfsign.pl --action decode --url "http//mydist.cloudfront.net/?Signature=AGO-PgxkYo99MkJFHvjfGXjG1QDEXeaDb4Qtzmy85wqyJjK7eKojQWa4BCRcow__&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovLypicmFkbS5qcGciLCJDb25kaXRpb24iOnsiSXBBZGRyZXNzIjp7IkFXUzpTb3VyY2VJcCI6IjEwLjUyLjE3LjkvMCJ9LCJEYXRlR3JlYXRlclRoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTI1MjUyMDgzMH19fV19Cg__&Key-Pair-Id=mykey"


To generate an RSA key pair, you can use openssl and the following commands:

# Generate a 2048 bit key pair
openssl genrsa -out private-key.pem 2048
openssl rsa -in private-key.pem -pubout -out public-key.pem


=head1 OPTIONS

=over 8

=item B<--help>

Print a help message and exits.

=item B<--action> [action]

The action to execute.  action can be one of:

  encode - Generate a signed URL (using a canned policy or a user policy)
  decode - Decode a signed URL

=item B<--url>

The URL to en/decode

=item B<--stream>

The stream to en/decode

=item B<--private-key>

The path to your private key.

=item B<--key-pair-id>

The key pair identifier.

=item B<--policy>

The CloudFront policy document.

=item B<--expires>

The Unix epoch time when the URL is to expire. If both this option and
the --policy option are specified, --policy will be used. Otherwise, this 
option alone will use a canned policy.

=back

=cut

use strict;
use warnings;

# you might need to use CPAN to get these modules.
# run perl -MCPAN -e "install <module>" to get them.
# The openssl command line will also need to be in your $PATH.
use File::Temp qw/tempfile/;
use File::Slurp;
use Getopt::Long;
use IPC::Open2;
use MIME::Base64 qw(encode_base64 decode_base64);
use Pod::Usage;
use URI;

my $CANNED_POLICY 
    = '{"Statement":[{"Resource":"<RESOURCE>","Condition":{"DateLessThan":{"AWS:EpochTime":<EXPIRES>}}}]}';

my $POLICY_PARAM      = "Policy";
my $EXPIRES_PARAM     = "Expires";
my $SIGNATURE_PARAM   = "Signature";
my $KEY_PAIR_ID_PARAM = "Key-Pair-Id";

my $verbose = 0;
my $policy_filename = "";
my $expires_epoch = 0;
my $action = "";
my $help = 0;
my $key_pair_id = "";
my $url = "";
my $stream = "";
my $private_key_filename = "";

my $result = GetOptions("action=s"      => \$action,
                        "policy=s"      => \$policy_filename,
                        "expires=i"     => \$expires_epoch,
                        "private-key=s" => \$private_key_filename,
                        "key-pair-id=s" => \$key_pair_id,
                        "verbose"       => \$verbose,
                        "help"          => \$help,
                        "url=s"         => \$url,
                        "stream=s"      => \$stream,
                    );

if ($help or !$result) {
    pod2usage(1);
    exit;
}

if ($url eq "" and $stream eq "") {
    print STDERR "Must include a stream or a URL to encode or decode with the --stream or --url option\n";
    exit;
}

if ($url ne "" and $stream ne "") {
    print STDERR "Only one of --url and --stream may be specified\n";
    exit;
}

if ($url ne "" and !is_url_valid($url)) {
    exit;
}

if ($stream ne "") {
    exit unless is_stream_valid($stream);

    # The signing mechanism is identical, so from here on just pretend we're
    # dealing with a URL
    $url = $stream;
} 

if ($action eq "encode") {
    # The encode action will generate a private content URL given a base URL, 
    # a policy file (or an expires timestamp) and a key pair id parameter
    my $private_key;
    my $public_key;
    my $public_key_file;
    
    my $policy;
    if ($policy_filename eq "") {
        if ($expires_epoch == 0) {
            print STDERR "Must include policy filename with --policy argument or an expires" . 
                          "time using --expires\n";            
        }
        
        $policy = $CANNED_POLICY;
        $policy =~ s/<EXPIRES>/$expires_epoch/g;
        $policy =~ s/<RESOURCE>/$url/g;
    } else {
        if (! -e $policy_filename) {
            print STDERR "Policy file $policy_filename does not exist\n";
            exit;
        }
        $expires_epoch = 0; # ignore if set
        $policy = read_file($policy_filename);
    }

    if ($private_key_filename eq "") {
        print STDERR "You must specific the path to your private key file with --private-key\n";
        exit;
    }

    if (! -e $private_key_filename) {
        print STDERR "Private key file $private_key_filename does not exist\n";
        exit;
    }

    if ($key_pair_id eq "") {
        print STDERR "You must specify a key pair id with --key-pair-id\n";
        exit;
    }

    my $encoded_policy = url_safe_base64_encode($policy);
    my $signature = rsa_sha1_sign($policy, $private_key_filename);
    my $encoded_signature = url_safe_base64_encode($signature);

    my $generated_url = create_url($url, $encoded_policy, $encoded_signature, $key_pair_id, $expires_epoch);


    if ($stream ne "") {
        print "Encoded stream (for use within a swf):\n" . $generated_url . "\n";
        print "Encoded and escaped stream (for use on a webpage):\n" .  escape_url_for_webpage($generated_url) . "\n"; 
    } else {
        print "Encoded URL:\n" . $generated_url . "\n";
    }
} elsif ($action eq "decode") {
    my $decoded = decode_url($url);
    if (!$decoded) {
        print STDERR "Improperly formed URL\n";
        exit;
    }

    print_decoded_url($decoded);
} else {
    # No action specified, print help.  But only if this is run as a program (caller will be empty)
    pod2usage(1) unless caller();
}

# Decode a private content URL into its component parts
sub decode_url {
    my $url = shift;

    if ($url =~ /(.*)\?(.*)/) {
        my $base_url = $1;
        my $params = $2;

        my @unparsed_params = split(/&/, $params);
        my %params = ();
        foreach my $param (@unparsed_params) {
            my ($key, $val) = split(/=/, $param);
            $params{$key} = $val;
        }

        my $encoded_signature = "";
        if (exists $params{$SIGNATURE_PARAM}) {
            $encoded_signature = $params{"Signature"};
        } else {
            print STDERR "Missing Signature URL parameter\n";
            return 0;
        }

        my $encoded_policy = "";
        if (exists $params{$POLICY_PARAM}) {
            $encoded_policy = $params{$POLICY_PARAM};
        } else {
            if (!exists $params{$EXPIRES_PARAM}) {
                print STDERR "Either the Policy or Expires URL parameter needs to be specified\n";
                return 0;    
            }
            
            my $expires = $params{$EXPIRES_PARAM};
            
            my $policy = $CANNED_POLICY;
            $policy =~ s/<EXPIRES>/$expires/g;
            
            my $url_without_cf_params = $url;
            $url_without_cf_params =~ s/$SIGNATURE_PARAM=[^&]*&?//g;
            $url_without_cf_params =~ s/$POLICY_PARAM=[^&]*&?//g;
            $url_without_cf_params =~ s/$EXPIRES_PARAM=[^&]*&?//g;
            $url_without_cf_params =~ s/$KEY_PAIR_ID_PARAM=[^&]*&?//g;
            
            if ($url_without_cf_params =~ /(.*)\?$/) {
                $url_without_cf_params = $1;
            }
            
            $policy =~ s/<RESOURCE>/$url_without_cf_params/g;
            
            $encoded_policy = url_safe_base64_encode($policy);
        }

        my $key = "";
        if (exists $params{$KEY_PAIR_ID_PARAM}) {
            $key = $params{$KEY_PAIR_ID_PARAM};
        } else {
            print STDERR "Missing $KEY_PAIR_ID_PARAM parameter\n";
            return 0;
        }

        my $policy = url_safe_base64_decode($encoded_policy);

        my %ret = ();
        $ret{"base_url"} = $base_url;
        $ret{"policy"} = $policy;
        $ret{"key"} = $key;

        return \%ret;
    } else {
        return 0;
    }
}

# Print a decoded URL out
sub print_decoded_url {
    my $decoded = shift;

    print "Base URL: \n" . $decoded->{"base_url"} . "\n";
    print "Policy: \n" . $decoded->{"policy"} . "\n";
    print "Key: \n" . $decoded->{"key"} . "\n";
}

# Encode a string with base 64 encoding and replace some invalid URL characters
sub url_safe_base64_encode {
    my ($value) = @_;

    my $result = encode_base64($value);
    $result =~ tr|+=/|-_~|;

    return $result;
}

# Decode a string with base 64 encoding.  URL-decode the string first
# followed by reversing any special character ("+=/") translation.
sub url_safe_base64_decode {
    my ($value) = @_;

    $value =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
    $value =~ tr|-_~|+=/|;

    my $result = decode_base64($value);

    return $result;
}

# Create a private content URL
sub create_url {
    my ($path, $policy, $signature, $key_pair_id, $expires) = @_;
    
    my $result;
    my $separator = $path =~ /\?/ ? '&' : '?';
    if ($expires) {
        $result = "$path$separator$EXPIRES_PARAM=$expires&$SIGNATURE_PARAM=$signature&$KEY_PAIR_ID_PARAM=$key_pair_id";
    } else {
        $result = "$path$separator$POLICY_PARAM=$policy&$SIGNATURE_PARAM=$signature&$KEY_PAIR_ID_PARAM=$key_pair_id";
    }
    $result =~ s/\n//g;

    return $result;
}

# Sign a document with given private key file.
# The first argument is the document to sign
# The second argument is the name of the private key file
sub rsa_sha1_sign {
    my ($to_sign, $pvkFile) = @_;
    print "openssl sha1 -sign $pvkFile $to_sign\n";

    return write_to_program($pvkFile, $to_sign);
}

# Helper function to write data to a program
sub write_to_program {
my ($keyfile, $data) = @_;
unlink "temp_policy.dat" if (-e "temp_policy.dat");
unlink "temp_sign.dat" if (-e "temp_sign.dat");

write_file("temp_policy.dat", $data);

system("openssl dgst -sha1 -sign \"$keyfile\" -out temp_sign.dat temp_policy.dat");

my $output = read_file("temp_sign.dat");

    return $output;
}

# Read a file into a string and return the string
sub read_file {
    my ($file) = @_;

    open(INFILE, "<$file") or die("Failed to open $file: $!");
    my $str = join('', <INFILE>);
    close INFILE;

    return $str;
}

sub is_url_valid {
    my ($url) = @_;

    # HTTP distributions start with http[s]:// and are the correct thing to sign
    if ($url =~ /^https?:\/\//) {
        return 1;
    } else {
        print STDERR "CloudFront requires absolute URLs for HTTP distributions\n";
        return 0;
    }
}

sub is_stream_valid {
    my ($stream) = @_;

    if ($stream =~ /^rtmp:\/\// or $stream =~ /^\/?cfx\/st/) {
        print STDERR "Streaming distributions require that only the stream name is signed.\n";
        print STDERR "The stream name is everything after, but not including, cfx/st/\n";
        return 0;
    } else {
        return 1;
    }
}

# flash requires that the query parameters in the stream name are url
# encoded when passed in through javascript, etc.  This sub handles the minimal
# required url encoding.
sub escape_url_for_webpage {
    my ($url) = @_;

    $url =~ s/\?/%3F/g;
    $url =~ s/=/%3D/g;
    $url =~ s/&/%26/g;

    return $url;
}

1;
```

# 使用 PHP 建立 URL 簽章
<a name="CreateURL_PHP"></a>

任何執行 PHP 的 Web 伺服器都可以使用 PHP 範例程式碼為私有 CloudFront 分佈建立政策聲明和簽章。該完整範例以已簽署 URL 連結建立一個正常運作網頁，該連結使用 CloudFront 串流播放視訊串流。您可以從 [demo-php.zip](samples/demo-php.zip) 檔案下載完整範例。

**備註**  
建立 URL 簽章只是私有內容提供服務的程序的一部分，以使用簽章 URL。如需有關整個程序的詳細資訊，請參閱 [使用已簽署 URL](private-content-signed-urls.md)。
您還可以使用 適用於 PHP 的 AWS SDK中的 `UrlSigner` 類別建立簽章的 URL。如需詳細資訊，請參閱 *適用於 PHP 的 AWS SDK API 參考*中的 [Class UrlSigner](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CloudFront.UrlSigner.html)。
在`openssl_sign`呼叫中，請注意`OPENSSL_ALGO_SHA256`，做為第四個引數傳遞 會切換到 SHA-256。([使用 PHP 建立已簽署 Cookie](signed-cookies-PHP.md)如需完整範例，另請參閱 。)

**Topics**
+ [建立 RSA SHA-1 簽章](#sample-rsa-sign)
+ [建立標準政策](#sample-canned-policy)
+ [建立自訂政策](#sample-custom-policy)
+ [完整程式碼範例](#full-example)

下列各節將程式碼範例細分為個別部分。您可以在下面找到 [完整程式碼範例](#full-example)。

## 建立 RSA SHA-1 簽章
<a name="sample-rsa-sign"></a>

此程式碼會執行下列操作：
+ `rsa_sha1_sign` 函數會雜湊並簽署政策陳述式。所需的引數為政策陳述式，以及與您分佈之信任金鑰群組中公有金鑰對應的私有金鑰。
+ 接著，該 `url_safe_base64_encode` 函數會建立已簽章的 URL 安全版本。

```
function rsa_sha1_sign($policy, $private_key_filename) {
    $signature = "";

    // load the private key
    $fp = fopen($private_key_filename, "r");
    $priv_key = fread($fp, 8192);
    fclose($fp);
    $pkeyid = openssl_get_privatekey($priv_key);

    // compute signature
    openssl_sign($policy, $signature, $pkeyid);

    // free the key from memory
    openssl_free_key($pkeyid);

    return $signature;
}

function url_safe_base64_encode($value) {
    $encoded = base64_encode($value);
    // replace unsafe characters +, = and / with 
    // the safe characters -, _ and ~
    return str_replace(
        array('+', '=', '/'),
        array('-', '_', '~'),
        $encoded);
}
```

下列程式碼片段使用 `get_canned_policy_stream_name()` 和 `get_custom_policy_stream_name()` 函數來建立標準和自訂政策。CloudFront 使用政策來建立串流影片的 URL，包括指定過期時間。

然後，您可以使用標準政策或自訂政策來決定如何管理對內容的存取。如需選擇哪個項目的詳細資訊，請參閱 [決定對已簽署 URL 使用標準或自訂政策](private-content-signed-urls.md#private-content-choosing-canned-custom-policy) 一節。

## 建立標準政策
<a name="sample-canned-policy"></a>

下列範例程式碼會建構簽章的*標準*政策陳述式。

**注意**  
`$expires` 變數是日期/時間戳記，必須整數，而不是字串。

```
function get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $expires) {
    // this policy is well known by CloudFront, but you still need to sign it, since it contains your parameters
    $canned_policy = '{"Statement":[{"Resource":"' . $video_path . '","Condition":{"DateLessThan":{"AWS:EpochTime":'. $expires . '}}}]}';
    // the policy contains characters that cannot be part of a URL, so we base64 encode it
    $encoded_policy = url_safe_base64_encode($canned_policy);
    // sign the original policy, not the encoded version
    $signature = rsa_sha1_sign($canned_policy, $private_key_filename);
    // make the signature safe to be included in a URL
    $encoded_signature = url_safe_base64_encode($signature);

    // combine the above into a stream name
    $stream_name = create_stream_name($video_path, null, $encoded_signature, $key_pair_id, $expires);
    // URL-encode the query string characters
    return $stream_name;
}
```

如需有關標準政策的詳細資訊，請參閱 [使用標準政策建立已簽署 URL](private-content-creating-signed-url-canned-policy.md)。

## 建立自訂政策
<a name="sample-custom-policy"></a>

下列範例程式碼會建構簽章的*自訂*政策陳述式。

```
function get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy) {
    // the policy contains characters that cannot be part of a URL, so we base64 encode it
    $encoded_policy = url_safe_base64_encode($policy);
    // sign the original policy, not the encoded version
    $signature = rsa_sha1_sign($policy, $private_key_filename);
    // make the signature safe to be included in a URL
    $encoded_signature = url_safe_base64_encode($signature);

    // combine the above into a stream name
    $stream_name = create_stream_name($video_path, $encoded_policy, $encoded_signature, $key_pair_id, null);
    // URL-encode the query string characters
    return $stream_name;
}
```

如需有關自訂政策的詳細資訊，請參閱 [使用自訂政策建立已簽署 URL](private-content-creating-signed-url-custom-policy.md)。

## 完整程式碼範例
<a name="full-example"></a>

下面的範例程式碼提供了使用 PHP 建立 CloudFront 簽章 URL 的完整示範。您可以從 [demo-php.zip](samples/demo-php.zip) 檔案下載完整範例。

您可以在下列範例中修改 `$policy` `Condition` 元素，以允許 IPv4 與 IPv6 位址範圍。如需範例，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[在 IAM 政策中使用 IPv6 位址](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ipv6-access.html#ipv6-access-iam)。

```
<?php

function rsa_sha1_sign($policy, $private_key_filename) {
    $signature = "";

    // load the private key
    $fp = fopen($private_key_filename, "r");
    $priv_key = fread($fp, 8192);
    fclose($fp);
    $pkeyid = openssl_get_privatekey($priv_key);

    // compute signature
    openssl_sign($policy, $signature, $pkeyid);

    // free the key from memory
    openssl_free_key($pkeyid);

    return $signature;
}

function url_safe_base64_encode($value) {
    $encoded = base64_encode($value);
    // replace unsafe characters +, = and / with the safe characters -, _ and ~
    return str_replace(
        array('+', '=', '/'),
        array('-', '_', '~'),
        $encoded);
}

function create_stream_name($stream, $policy, $signature, $key_pair_id, $expires) {
    $result = $stream;
    // if the stream already contains query parameters, attach the new query parameters to the end
    // otherwise, add the query parameters
    $separator = strpos($stream, '?') == FALSE ? '?' : '&';
    // the presence of an expires time means we're using a canned policy
    if($expires) {
        $result .= $separator . "Expires=" . $expires . "&Signature=" . $signature . "&Key-Pair-Id=" . $key_pair_id;
    }
    // not using a canned policy, include the policy itself in the stream name
    else {
        $result .= $separator . "Policy=" . $policy . "&Signature=" . $signature . "&Key-Pair-Id=" . $key_pair_id;
    }

    // new lines would break us, so remove them
    return str_replace('\n', '', $result);
}


function get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $expires) {
    // this policy is well known by CloudFront, but you still need to sign it, since it contains your parameters
    $canned_policy = '{"Statement":[{"Resource":"' . $video_path . '","Condition":{"DateLessThan":{"AWS:EpochTime":'. $expires . '}}}]}';
    // the policy contains characters that cannot be part of a URL, so we base64 encode it
    $encoded_policy = url_safe_base64_encode($canned_policy);
    // sign the original policy, not the encoded version
    $signature = rsa_sha1_sign($canned_policy, $private_key_filename);
    // make the signature safe to be included in a URL
    $encoded_signature = url_safe_base64_encode($signature);

    // combine the above into a stream name
    $stream_name = create_stream_name($video_path, null, $encoded_signature, $key_pair_id, $expires);
    // URL-encode the query string characters
    return $stream_name;
}

function get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy) {
    // the policy contains characters that cannot be part of a URL, so we base64 encode it
    $encoded_policy = url_safe_base64_encode($policy);
    // sign the original policy, not the encoded version
    $signature = rsa_sha1_sign($policy, $private_key_filename);
    // make the signature safe to be included in a URL
    $encoded_signature = url_safe_base64_encode($signature);

    // combine the above into a stream name
    $stream_name = create_stream_name($video_path, $encoded_policy, $encoded_signature, $key_pair_id, null);
    // URL-encode the query string characters
    return $stream_name;
}


// Path to your private key.  Be very careful that this file is not accessible
// from the web!

$private_key_filename = '/home/test/secure/example-priv-key.pem';
$key_pair_id = 'K2JCJMDEHXQW5F';

// Make sure you have "Restrict viewer access" enabled on this path behaviour and using the above Trusted key groups (recommended).
$video_path = 'https://example.com/secure/example.mp4';

$expires = time() + 300; // 5 min from now
$canned_policy_stream_name = get_canned_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $expires);

// Get the viewer real IP from the x-forward-for header as $_SERVER['REMOTE_ADDR'] will return viewer facing IP. An alternative option is to use CloudFront-Viewer-Address header. Note that this header is a trusted CloudFront immutable header. Example format: IP:PORT ("CloudFront-Viewer-Address": "1.2.3.4:12345")
$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$policy =
'{'.
    '"Statement":['.
        '{'.
            '"Resource":"'. $video_path . '",'.
            '"Condition":{'.
                '"IpAddress":{"AWS:SourceIp":"' . $client_ip . '/32"},'.
                '"DateLessThan":{"AWS:EpochTime":' . $expires . '}'.
            '}'.
        '}'.
    ']' .
    '}';
$custom_policy_stream_name = get_custom_policy_stream_name($video_path, $private_key_filename, $key_pair_id, $policy);

?>

<html>

<head>
    <title>CloudFront</title>
</head>

<body>
    <h1>Amazon CloudFront</h1>
    <h2>Canned Policy</h2>
    <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?></h3>
    <br />

    <div id='canned'>The canned policy video will be here: <br>
    
        <video width="640" height="360" autoplay muted controls>
        <source src="<?php echo $canned_policy_stream_name; ?>" type="video/mp4">
        Your browser does not support the video tag.
        </video>
    </div>

    <h2>Custom Policy</h2>
    <h3>Expires at <?php echo gmdate('Y-m-d H:i:s T', $expires); ?> only viewable by IP <?php echo $client_ip; ?></h3>
    <div id='custom'>The custom policy video will be here: <br>

         <video width="640" height="360" autoplay muted controls>
         <source src="<?php echo $custom_policy_stream_name; ?>" type="video/mp4">
         Your browser does not support the video tag.
        </video>
    </div> 

</body>

</html>
```

如需其他 URL 簽章範例，請參閱下列主題：
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 C\$1 和 .NET 架構建立 URL 簽章](CreateSignatureInCSharp.md)
+ [使用 Java 建立 URL 簽章](CFPrivateDistJavaDevelopment.md)

您可以使用已簽署 Cookie，而不是使用已簽署 URL 來建立簽章。如需詳細資訊，請參閱[使用 PHP 建立已簽署 Cookie](signed-cookies-PHP.md)。

# 使用 C\$1 和 .NET 架構建立 URL 簽章
<a name="CreateSignatureInCSharp"></a>

本節中的 C\$1 範例實作應用程式範例，示範如何使用標準和自訂政策聲明為 CloudFront 私有分佈建立簽章。此範例包含使用 [適用於 .NET 的 AWS SDK](https://aws.amazon.com/sdkfornet) 的公用程式函數，這些函數在 .NET 應用程式中非常實用。

您也可以使用 適用於 .NET 的 SDK建立已簽章的 URL 和已簽章的 Cookie。在 *適用於 .NET 的 SDK API 參考*中，請參閱下列主題：
+ **已簽署 URL** – [AmazonCloudFrontUrlSigner](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudFront/TCloudFrontUrlSigner.html) 
+ **已簽署 Cookie** – [AmazonCloudFrontCookieSigner](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudFront/TCloudFrontCookieSigner.html) 

若要下載程式碼，請前往[使用 C\$1 的簽章程式碼](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/AWS_PrivateCF_Distributions.zip)。

**備註**  
`AmazonCloudFrontUrlSigner` 和 `AmazonCloudFrontCookieSigner` 類別已移至單獨的套件。如需有關如何使用的詳細資訊，請參閱《*適用於 .NET 的 AWS SDK (V4) 開發人員指南*》中的 [CookieSigner 和 UrlSigner](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html#net-dg-v4-CookieSigner-UrlSigner)。
建立 URL 簽章只是私有內容提供服務的程序的一部分，以使用簽章 URL。如需詳細資訊，請參閱[使用已簽署 URL](private-content-signed-urls.md)。若需有關使用已簽署 Cookie 的詳細資訊，請參閱 [使用已簽署 Cookie](private-content-signed-cookies.md)。
在 RSA 簽署呼叫中，請注意 `SHA1`可以在雜湊演算法參數`SHA256`中取代為 。

## 在 .NET Framework 中使用 RSA 金鑰
<a name="rsa-key-sdk-net"></a>

若要在 .NET Framework 中使用 RSA 金鑰，您必須將 AWS 提供的 .pem 檔案轉換為 .NET Framework 使用的 XML 格式。

轉換後，RSA 私有金鑰檔案的格式如下：

**Example ：XML .NET 架構格式的 RSA 私有金鑰**  <a name="RSAPrivateKeyXML.NETFrameworkFormat"></a>

```
<RSAKeyValue>
  <Modulus>
    wO5IvYCP5UcoCKDo1dcspoMehWBZcyfs9QEzGi6Oe5y+ewGr1oW+vB2GPB
    ANBiVPcUHTFWhwaIBd3oglmF0lGQljP/jOfmXHUK2kUUnLnJp+oOBL2NiuFtqcW6h/L5lIpD8Yq+NRHg
    Ty4zDsyr2880MvXv88yEFURCkqEXAMPLE=
  </Modulus>
  <Exponent>AQAB</Exponent>
  <P>
    5bmKDaTz
    npENGVqz4Cea8XPH+sxt+2VaAwYnsarVUoSBeVt8WLloVuZGG9IZYmH5KteXEu7fZveYd9UEXAMPLE==
  </P>
  <Q>
    1v9l/WN1a1N3rOK4VGoCokx7kR2SyTMSbZgF9IWJNOugR/WZw7HTnjipO3c9dy1Ms9pUKwUF4
    6d7049EXAMPLE==
  </Q>
  <DP>
    RgrSKuLWXMyBH+/l1Dx/I4tXuAJIrlPyo+VmiOc7b5NzHptkSHEPfR9s1
    OK0VqjknclqCJ3Ig86OMEtEXAMPLE==
  </DP>
  <DQ>
    pjPjvSFw+RoaTu0pgCA/jwW/FGyfN6iim1RFbkT4
    z49DZb2IM885f3vf35eLTaEYRYUHQgZtChNEV0TEXAMPLE==
  </DQ>
  <InverseQ>
    nkvOJTg5QtGNgWb9i
    cVtzrL/1pFEOHbJXwEJdU99N+7sMK+1066DL/HSBUCD63qD4USpnf0myc24in0EXAMPLE==</InverseQ>
  <D>
      Bc7mp7XYHynuPZxChjWNJZIq+A73gm0ASDv6At7F8Vi9r0xUlQe/v0AQS3ycN8QlyR4XMbzMLYk
      3yjxFDXo4ZKQtOGzLGteCU2srANiLv26/imXA8FVidZftTAtLviWQZBVPTeYIA69ATUYPEq0a5u5wjGy
      UOij9OWyuEXAMPLE=
   </D>
</RSAKeyValue>
```

## C\$1 的標準政策簽章方式
<a name="canned-policy-signed-url-net"></a>

以下 C\$1 程式碼會透過執行以下程序建立使用標準政策簽章的 URL：
+ 建立政策聲明。
+ 使用 SHA1 對政策陳述式進行雜湊處理，並使用 RSA 和其對應的公有金鑰在信任金鑰組中的私有金鑰對結果進行簽署。
+ Base64 編碼雜湊和簽章的政策聲明，並取代特殊字元，以使字串安全地用作 URL 請求參數。
+ 串連值。

如需完整的實作，請參閱[使用 C\$1 的簽章程式碼](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/AWS_PrivateCF_Distributions.zip)範例。

**注意**  
當您將公有金鑰上傳至 CloudFront 時，會傳回 `keyId`。如需詳細資訊，請參閱 ![\[6\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/images/callouts/6.png)[ &Key-Pair-Id](private-content-creating-signed-url-canned-policy.md)。

**Example ：C\$1 的標準政策簽章方式**  <a name="ExampleCannedPolicySigningMethod-CSharp"></a>

```
public static string ToUrlSafeBase64String(byte[] bytes)
{
    return System.Convert.ToBase64String(bytes)
        .Replace('+', '-')
        .Replace('=', '_')
        .Replace('/', '~');
}

public static string CreateCannedPrivateURL(string urlString, 
    string durationUnits, string durationNumber, string pathToPolicyStmnt, 
    string pathToPrivateKey, string keyId)
{
    // args[] 0-thisMethod, 1-resourceUrl, 2-seconds-minutes-hours-days 
    // to expiration, 3-numberOfPreviousUnits, 4-pathToPolicyStmnt, 
    // 5-pathToPrivateKey, 6-keyId

    TimeSpan timeSpanInterval = GetDuration(durationUnits, durationNumber);

    // Create the policy statement.
    string strPolicy = CreatePolicyStatement(pathToPolicyStmnt,
        urlString, 
        DateTime.Now, 
        DateTime.Now.Add(timeSpanInterval), 
        "0.0.0.0/0");
    if ("Error!" == strPolicy) return "Invalid time frame." + 
        "Start time cannot be greater than end time.";

    // Copy the expiration time defined by policy statement.
    string strExpiration = CopyExpirationTimeFromPolicy(strPolicy);

    // Read the policy into a byte buffer.
    byte[] bufferPolicy = Encoding.ASCII.GetBytes(strPolicy);

    // Initialize the SHA1CryptoServiceProvider object and hash the policy data.
    using (SHA1CryptoServiceProvider 
        cryptoSHA1 = new SHA1CryptoServiceProvider())
    {
        bufferPolicy = cryptoSHA1.ComputeHash(bufferPolicy);

        // Initialize the RSACryptoServiceProvider object.
        RSACryptoServiceProvider providerRSA = new RSACryptoServiceProvider();
        XmlDocument xmlPrivateKey = new XmlDocument();

        // Load your private key, which you created by converting your 
        // .pem file to the XML format that the .NET framework uses.  
        // Several tools are available. 
        xmlPrivateKey.Load(pathToPrivateKey);

        // Format the RSACryptoServiceProvider providerRSA and 
        // create the signature.
        providerRSA.FromXmlString(xmlPrivateKey.InnerXml);
        RSAPKCS1SignatureFormatter rsaFormatter = 
            new RSAPKCS1SignatureFormatter(providerRSA);
        rsaFormatter.SetHashAlgorithm("SHA1");
        byte[] signedPolicyHash = rsaFormatter.CreateSignature(bufferPolicy);

        // Convert the signed policy to URL-safe base64 encoding and 
        // replace unsafe characters + = / with the safe characters - _ ~
        string strSignedPolicy = ToUrlSafeBase64String(signedPolicyHash);

        // Concatenate the URL, the timestamp, the signature, 
        // and the key pair ID to form the signed URL.
        return urlString + 
            "?Expires=" + 
            strExpiration + 
            "&Signature=" + 
            strSignedPolicy + 
            "&Key-Pair-Id=" + 
            keyId;
    }
}
```

## C\$1 的自訂政策簽章方式
<a name="custom-policy-signed-url-net"></a>

以下 C\$1 程式碼透過執行以下步驟建立使用自訂政策簽章的 URL：

1. 建立政策聲明。

1. Base64 編碼政策聲明，並取代特殊字元，以使字串安全地用作 URL 請求參數。

1. 使用 SHA1 對政策陳述式進行雜湊處理，並使用 RSA 和其對應的公有金鑰在信任金鑰組中的私有金鑰對結果進行加密。

1. Base64 編碼雜湊政策聲明，並取代特殊字元，以使字串安全地用作 URL 請求參數。

1. 串連值。

如需完整的實作，請參閱[使用 C\$1 的簽章程式碼](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/samples/AWS_PrivateCF_Distributions.zip)範例。

**注意**  
當您將公有金鑰上傳至 CloudFront 時，會傳回 `keyId`。如需詳細資訊，請參閱 ![\[6\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/images/callouts/6.png)[ &Key-Pair-Id](private-content-creating-signed-url-canned-policy.md)。

**Example ：C\$1 的自訂政策簽章方式**  <a name="ExampleCustomPolicySigningMethod-CSharp"></a>

```
public static string ToUrlSafeBase64String(byte[] bytes)
{
    return System.Convert.ToBase64String(bytes)
        .Replace('+', '-')
        .Replace('=', '_')
        .Replace('/', '~');
}

public static string CreateCustomPrivateURL(string urlString, 
    string durationUnits, string durationNumber, string startIntervalFromNow, 
    string ipaddress, string pathToPolicyStmnt, string pathToPrivateKey, 
    string keyId)
{
    // args[] 0-thisMethod, 1-resourceUrl, 2-seconds-minutes-hours-days 
    // to expiration, 3-numberOfPreviousUnits, 4-starttimeFromNow, 
    // 5-ip_address, 6-pathToPolicyStmt, 7-pathToPrivateKey, 8-keyId

    TimeSpan timeSpanInterval = GetDuration(durationUnits, durationNumber);
    TimeSpan timeSpanToStart = GetDurationByUnits(durationUnits, 
        startIntervalFromNow);
    if (null == timeSpanToStart) 
        return "Invalid duration units." + 
            "Valid options: seconds, minutes, hours, or days";
            
    string strPolicy = CreatePolicyStatement(
        pathToPolicyStmnt, urlString, DateTime.Now.Add(timeSpanToStart), 
        DateTime.Now.Add(timeSpanInterval), ipaddress);

    // Read the policy into a byte buffer.
    byte[] bufferPolicy = Encoding.ASCII.GetBytes(strPolicy);

    // Convert the policy statement to URL-safe base64 encoding and 
    // replace unsafe characters + = / with the safe characters - _ ~

    string urlSafePolicy = ToUrlSafeBase64String(bufferPolicy);

    // Initialize the SHA1CryptoServiceProvider object and hash the policy data.
    byte[] bufferPolicyHash;
    using (SHA1CryptoServiceProvider cryptoSHA1 = 
        new SHA1CryptoServiceProvider())
    {
        bufferPolicyHash = cryptoSHA1.ComputeHash(bufferPolicy);

        // Initialize the RSACryptoServiceProvider object.
        RSACryptoServiceProvider providerRSA = new RSACryptoServiceProvider();
        XmlDocument xmlPrivateKey = new XmlDocument();

        // Load your private key, which you created by converting your 
        // .pem file to the XML format that the .NET framework uses.  
        // Several tools are available. 
        xmlPrivateKey.Load(pathToPrivateKey);

        // Format the RSACryptoServiceProvider providerRSA 
        // and create the signature.
        providerRSA.FromXmlString(xmlPrivateKey.InnerXml);
        RSAPKCS1SignatureFormatter RSAFormatter = 
            new RSAPKCS1SignatureFormatter(providerRSA);
        RSAFormatter.SetHashAlgorithm("SHA1");
        byte[] signedHash = RSAFormatter.CreateSignature(bufferPolicyHash);

        // Convert the signed policy to URL-safe base64 encoding and 
        // replace unsafe characters + = / with the safe characters - _ ~
        string strSignedPolicy = ToUrlSafeBase64String(signedHash);

        return urlString + 
            "?Policy=" + 
            urlSafePolicy + 
            "&Signature=" + 
            strSignedPolicy + 
            "&Key-Pair-Id=" + 
            keyId;
    }
}
```

## 適用於簽章產生的公用方法
<a name="utility-methods-signed-url"></a>

以下方法從檔案取得政策聲明和剖析簽章產生的時間間隔。

**Example ：適用於簽章產生的公用方法**  <a name="UtilityMethodsForSignatureGeneration"></a>

```
public static string CreatePolicyStatement(string policyStmnt, 
   string resourceUrl, 
   DateTime startTime, 
   DateTime endTime, 
   string ipAddress)
   
{
   // Create the policy statement.
   FileStream streamPolicy = new FileStream(policyStmnt, FileMode.Open, FileAccess.Read);
   using (StreamReader reader = new StreamReader(streamPolicy))
   {
      string strPolicy = reader.ReadToEnd();

      TimeSpan startTimeSpanFromNow = (startTime - DateTime.Now);
      TimeSpan endTimeSpanFromNow = (endTime - DateTime.Now);
      TimeSpan intervalStart = 
         (DateTime.UtcNow.Add(startTimeSpanFromNow)) - 
         new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
      TimeSpan intervalEnd = 
         (DateTime.UtcNow.Add(endTimeSpanFromNow)) - 
         new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

      int startTimestamp = (int)intervalStart.TotalSeconds; // START_TIME
      int endTimestamp = (int)intervalEnd.TotalSeconds;  // END_TIME

      if (startTimestamp > endTimestamp)
         return "Error!";

      // Replace variables in the policy statement.
      strPolicy = strPolicy.Replace("RESOURCE", resourceUrl);
      strPolicy = strPolicy.Replace("START_TIME", startTimestamp.ToString());
      strPolicy = strPolicy.Replace("END_TIME", endTimestamp.ToString());
      strPolicy = strPolicy.Replace("IP_ADDRESS", ipAddress);
      strPolicy = strPolicy.Replace("EXPIRES", endTimestamp.ToString());
      return strPolicy;
   }   
}

public static TimeSpan GetDuration(string units, string numUnits)
{
   TimeSpan timeSpanInterval = new TimeSpan();
   switch (units)
   {
      case "seconds":
         timeSpanInterval = new TimeSpan(0, 0, 0, int.Parse(numUnits));
         break;
      case "minutes":
         timeSpanInterval = new TimeSpan(0, 0, int.Parse(numUnits), 0);
         break;
      case "hours":
         timeSpanInterval = new TimeSpan(0, int.Parse(numUnits), 0 ,0);
         break;
      case "days":
         timeSpanInterval = new TimeSpan(int.Parse(numUnits),0 ,0 ,0);
         break;
      default:
         Console.WriteLine("Invalid time units;" + 
            "use seconds, minutes, hours, or days");
         break;
   }
   return timeSpanInterval;
}

private static TimeSpan GetDurationByUnits(string durationUnits, 
   string startIntervalFromNow)
{
   switch (durationUnits)
   {
      case "seconds":
         return new TimeSpan(0, 0, int.Parse(startIntervalFromNow));
      case "minutes":
         return new TimeSpan(0, int.Parse(startIntervalFromNow), 0);
      case "hours":
         return new TimeSpan(int.Parse(startIntervalFromNow), 0, 0);
      case "days":
         return new TimeSpan(int.Parse(startIntervalFromNow), 0, 0, 0);
      default:
         return new TimeSpan(0, 0, 0, 0);
   }
}

public static string CopyExpirationTimeFromPolicy(string policyStatement)
{
   int startExpiration = policyStatement.IndexOf("EpochTime");
   string strExpirationRough = policyStatement.Substring(startExpiration + 
      "EpochTime".Length);
   char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
         
   List<char> listDigits = new List<char>(digits);
   StringBuilder buildExpiration = new StringBuilder(20);
         
   foreach (char c in strExpirationRough)
   {
      if (listDigits.Contains(c))
         buildExpiration.Append(c);
   }
   return buildExpiration.ToString();   
}
```

另請參閱
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 PHP 建立 URL 簽章](CreateURL_PHP.md)
+ [使用 Java 建立 URL 簽章](CFPrivateDistJavaDevelopment.md)

# 使用 Java 建立 URL 簽章
<a name="CFPrivateDistJavaDevelopment"></a>

除了下列程式碼範例之外，您還可以使用 [適用於 Java 的 AWS SDK （版本 1) 中的`CloudFrontUrlSigner`公用程式類別](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cloudfront/CloudFrontUrlSigner.html)來建立 [CloudFront 簽章URLs](private-content-signed-urls.md)。

如需更多範例，請參閱 *AWS SDK 程式碼範例程式碼庫*中的[使用 AWS SDK 建立簽章URLs 和 Cookie](https://docs.aws.amazon.com/code-library/latest/ug/cloudfront_example_cloudfront_CloudFrontUtilities_section.html)。

**備註**  
建立簽署 URL 只是[透過 CloudFront 提供私有內容](PrivateContent.md)程序的一個環節。如需有關整個程序的詳細資訊，請參閱 [使用已簽署 URL](private-content-signed-urls.md)。
在`Signature.getInstance`通話中，請注意 `SHA1withRSA`可以取代為 `SHA256withRSA`。

**Example Java 政策和簽章加密方法**  <a name="ExampleJavaPolicyAndSignatureEncryptionMethods"></a>

```
package org.example;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import software.amazon.awssdk.services.cloudfront.CloudFrontUtilities;
import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest;
import software.amazon.awssdk.services.cloudfront.url.SignedUrl;

public class Main {

    public static void main(String[] args) throws Exception {
        CloudFrontUtilities cloudFrontUtilities = CloudFrontUtilities.create();
        Instant expirationDate = Instant.now().plus(7, ChronoUnit.DAYS);
        String resourceUrl = "https://a1b2c3d4e5f6g7.cloudfront.net";
        String keyPairId = "K1UA3WV15I7JSD";
        CannedSignerRequest cannedRequest = CannedSignerRequest.builder()
                .resourceUrl(resourceUrl)
                .privateKey(new java.io.File("/path/to/private_key.pem").toPath())
                .keyPairId(keyPairId)
                .expirationDate(expirationDate)
                .build();
        SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCannedPolicy(cannedRequest);
        String url = signedUrl.url();
        System.out.println(url);

    }
}
```

**Example 在 Java 中使用 SHA256 的固定政策簽署範例**  <a name="ExampleJavaPolicySHA256AndSignatureEncryptionMethods"></a>

```
package org.example;

import java.io.File;
import java.nio.file.Files;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;

public class Main {

    public static void main(String[] args) throws Exception {
        String resourceUrl = "https://a1b2c3d4e5f6g7.cloudfront.net/myfile.html";
        String keyPairId = "K1UA3WV15I7JSD";
        Instant expiration = Instant.now().plus(7, ChronoUnit.DAYS);
        PrivateKey privateKey = loadPrivateKey("/path/to/private_key.der");

        System.out.println(createSignedUrl(resourceUrl, keyPairId, privateKey, expiration, "SHA1"));
        System.out.println(createSignedUrl(resourceUrl, keyPairId, privateKey, expiration, "SHA256"));
    }

    static String createSignedUrl(String resourceUrl, String keyPairId,
                                  PrivateKey privateKey, Instant expiration,
                                  String hashAlgorithm) throws Exception {
        long epochSeconds = expiration.getEpochSecond();

        String policy = "{\"Statement\":[{\"Resource\":\"" + resourceUrl
                + "\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":" + epochSeconds + "}}}]}";

        String jcaAlgorithm = hashAlgorithm.equals("SHA256") ? "SHA256withRSA" : "SHA1withRSA";

        Signature sig = Signature.getInstance(jcaAlgorithm);
        sig.initSign(privateKey);
        sig.update(policy.getBytes("UTF-8"));
        String signature = base64UrlEncode(sig.sign());

        String url = resourceUrl
                + (resourceUrl.contains("?") ? "&" : "?")
                + "Expires=" + epochSeconds
                + "&Signature=" + signature
                + "&Key-Pair-Id=" + keyPairId;

        if (hashAlgorithm.equals("SHA256")) {
            url += "&Hash-Algorithm=SHA256";
        }

        return url;
    }

    static String base64UrlEncode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes)
                .replace('+', '-')
                .replace('=', '_')
                .replace('/', '~');
    }

    static PrivateKey loadPrivateKey(String path) throws Exception {
        byte[] keyBytes = Files.readAllBytes(new File(path).toPath());
        return KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
    }
}
```

另請參閱：
+ [使用 Perl 建立 URL 簽章](CreateURLPerl.md)
+ [使用 PHP 建立 URL 簽章](CreateURL_PHP.md)
+ [使用 C\$1 和 .NET 架構建立 URL 簽章](CreateSignatureInCSharp.md)

# 限制對 AWS 原始伺服器的存取
<a name="private-content-restricting-access-to-origin"></a>

您可以透過提供下列優點的方式設定 CloudFront 和一些 AWS 原始伺服器：
+ 限制對 AWS 原始伺服器的存取，使其無法公開存取。
+ 確定檢視器 （使用者） 只能透過指定的 CloudFront 分佈存取 AWS 原始伺服器中的內容。這可防止觀眾直接從原始伺服器或透過非預期的 CloudFront 分佈存取內容。

若要這樣做，請將 CloudFront 設定為將已驗證的請求傳送至原始 AWS 伺服器，並將 AWS 原始伺服器設定為僅允許從 CloudFront 存取已驗證的請求。如需詳細資訊，請參閱相容 AWS 原始伺服器類型的下列主題。

**Topics**
+ [限制對 AWS Elemental MediaPackage v2 原始伺服器的存取](private-content-restricting-access-to-mediapackage.md)
+ [限制對 AWS Elemental MediaStore 原始伺服器的存取](private-content-restricting-access-to-mediastore.md)
+ [限制對 AWS Lambda 函數 URL 原始伺服器的存取](private-content-restricting-access-to-lambda.md)
+ [限制對 Amazon S3 原始伺服器的存取](private-content-restricting-access-to-s3.md)
+ [使用 VPC 原始伺服器限制存取](private-content-vpc-origins.md)
+ [限制對 Amazon S3 多區域存取點原始伺服器的存取](private-content-restricting-access-to-s3-mrap.md)

# 限制對 AWS Elemental MediaPackage v2 原始伺服器的存取
<a name="private-content-restricting-access-to-mediapackage"></a>

CloudFront 提供*原始存取控制* (OAC)，以限制對 MediaPackage v2 原始伺服器的存取。

**注意**  
CloudFront OAC 僅支援 MediaPackage v2。不支援 MediaPackage v1。

**Topics**
+ [建立新的 OAC](#create-oac-overview-mediapackage)
+ [原始存取控制的進階設定](#oac-advanced-settings-mediapackage)

## 建立新的 OAC
<a name="create-oac-overview-mediapackage"></a>

完成下列主題中說明的步驟，在 CloudFront 中設定新的 OAC。

**Topics**
+ [先決條件](#oac-prerequisites-mediapackage)
+ [授予 CloudFront 存取 MediaPackage v2 原始伺服器的許可](#oac-permission-to-access-mediapackage)
+ [建立 OAC](#create-oac-mediapackage)

### 先決條件
<a name="oac-prerequisites-mediapackage"></a>

在建立和設定 OAC 之前，您必須擁有具 MediaPackage v2 原始伺服器的 CloudFront 分佈。如需詳細資訊，請參閱[使用 MediaStore 容器或 MediaPackage 頻道](DownloadDistS3AndCustomOrigins.md#concept_AWS_Media)。

### 授予 CloudFront 存取 MediaPackage v2 原始伺服器的許可
<a name="oac-permission-to-access-mediapackage"></a>

在您建立 OAC 或於 CloudFront 分佈中進行設定之前，請確定 CloudFront 具有存取 MediaPackage v2 原始伺服器的許可。在建立 CloudFront 分佈之後，但在將 OAC 新增至分佈組態中的 MediaPackage v2 原始伺服器之前，請執行此作業。

使用 IAM 政策允許 CloudFront 服務主體 (`cloudfront.amazonaws.com`) 存取原始伺服器。使用政策中的 `Condition` 元素，*僅*當請求代表包含 MediaPackage v2 原始伺服器的 CloudFront 分佈時，才允許 CloudFront 存取 MediaPackage v2 原始伺服器。這是您要新增 OAC 的 MediaPackage v2 原始伺服器分佈。

**Example ：IAM 政策，允許啟用 OAC 之 CloudFront 分佈的唯讀存取**  
下列政策允許 CloudFront 分佈 (`E1PDK09ESKHJWT`) 存取 MediaPackage v2 原始伺服器。原始伺服器是為 `Resource` 元素指定的 ARN。    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {"Service": "cloudfront.amazonaws.com"},
            "Action": "mediapackagev2:GetObject",
            "Resource": "arn:aws:mediapackagev2:us-east-1:123456789012:channelGroup/channel-group-name/channel/channel-name/originEndpoint/origin_endpoint_name",
            "Condition": {
                "StringEquals": {"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1PDK09ESKHJWT"}
            }
        }
    ]
}
```

**備註**  
如果您已啟用 MQAR 功能和原始存取控制 (OAC)，請將 `mediapackagev2:GetHeadObject` 動作新增至 IAM 政策。MQAR 需要此許可才能將 `HEAD` 請求傳送至 MediaPackage v2 原始伺服器。如需有關 MQAR 的詳細資訊，請參閱 [媒體品質感知彈性](media-quality-score.md)。
如果您建立的分佈沒有 MediaPackage v2 原始伺服器的許可，您可以從 CloudFront 主控台選擇**複製政策**，然後選擇**更新端點許可**。然後，您可以將複製的許可連接到端點。如需詳細資訊，請參閱《*AWS Elemental MediaPackage 使用者指南*》中的[端點政策欄位](https://docs.aws.amazon.com/mediapackage/latest/userguide/endpoints-policy.html)。

### 建立 OAC
<a name="create-oac-mediapackage"></a>

若要建立 OAC，您可以使用 AWS 管理主控台 CloudFormation、 AWS CLI、 或 CloudFront API。

------
#### [ Console ]

**建立 OAC**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 於左側導覽窗格中，選擇 **Origin access** (原始存取)。

1. 選擇 **Create control setting** (建立控制設定)。

1. 在**建立新 OAC** 表單上，執行下列操作：

   1. 輸入 OAC 的**名稱**，(選用) 輸入**描述**。

   1. 於**簽署行為**中，建議您保留預設設定 (**簽署請求 (建議使用)**)。如需詳細資訊，請參閱[原始存取控制的進階設定](#oac-advanced-settings-mediapackage)。

1. 針對**原始伺服器類型**，選擇 **MediaPackage V2**。

1. 選擇**建立**。
**提示**  
建立 OAC 之後，請記下**名稱**。您需要於下列程序中進行使用。

**將 OAC 新增至分佈中的 MediaPackage v2 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇一個您想要新增 OAC 之具 MediaPackage V2 原始伺服器的分佈，然後選擇**原始伺服器**標籤。

1. 選取您想要將 OAC 新增至的 MediaPackage v2 原始伺服器，然後選擇**編輯**。

1. 在原始伺服器的**Protocol** (通訊協定) 選取 **HTTPS only** (僅限 HTTPS)。

1. 在**原始存取控制**下拉式功能表中，選擇您想要使用的 OAC 名稱。

1. 選擇**儲存變更**。

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 MediaPackage v2 原始伺服器的所有請求。

------
#### [ CloudFormation ]

若要使用 建立 OAC CloudFormation，請使用 `AWS::CloudFront::OriginAccessControl` 資源類型。下列範例顯示用於建立 OAC 的 YAML 格式 CloudFormation 範本語法。

```
Type: AWS::CloudFront::OriginAccessControl
Properties: 
  OriginAccessControlConfig: 
      Description: An optional description for the origin access control
      Name: ExampleOAC
      OriginAccessControlOriginType: mediapackagev2
      SigningBehavior: always
      SigningProtocol: sigv4
```

如需詳細資訊，請參閱《*AWS CloudFormation 使用者指南*》中的 [AWS::CloudFront::OriginAccessControl](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html)。

------
#### [ CLI ]

若要使用 AWS Command Line Interface (AWS CLI) 建立原始存取控制，請使用 **aws cloudfront create-origin-access-control**命令。您可以使用輸入檔案來提供命令的輸入參數，而不必分別將每個個別參數指定為命令列輸入。

**如要建立原始存取控制 (包含輸入檔案的 CLI)**

1. 使用下列命令建立名為 `origin-access-control.yaml` 的檔案。這個檔案中包含 **create-origin-access-control** 命令的所有輸入參數。

   ```
   aws cloudfront create-origin-access-control --generate-cli-skeleton yaml-input > origin-access-control.yaml
   ```

1. 開啟您剛才建立的 `origin-access-control.yaml` 檔案。編輯檔案以新增 OAC 的名稱、說明 (選用)，並將 `SigningBehavior` 變更為 `always`。接著儲存檔案。

   如需其他 OAC 設定的相關資訊，請參閱 [原始存取控制的進階設定](#oac-advanced-settings-mediapackage)。

1. 使用下列命令，利用 `origin-access-control.yaml` 檔案中的輸入參數建立原始存取控制。

   ```
   aws cloudfront create-origin-access-control --cli-input-yaml file://origin-access-control.yaml
   ```

   記下命令輸出中的 `Id` 值，您需要其將 OAC 新增至 CloudFront 分佈中的 MediaPackage v2 原始伺服器。

**如要將 OAC 附加至現有分佈 (包含輸入檔案的 CLI) 中的 MediaPackage v2 原始伺服器**

1. 使用下列命令來儲存您想要新增之 CloudFront 分佈的分佈組態。分佈必須具有 MediaPackage v2 原始伺服器。

   ```
   aws cloudfront get-distribution-config --id <CloudFront distribution ID> --output yaml > dist-config.yaml
   ```

1. 開啟您剛才建立且命名為 `dist-config.yaml` 的檔案。編輯檔案，進行下列變更：
   + 於 `Origins` 物件中，將 OAC 的 ID 新增至名為 `OriginAccessControlId` 的欄位。
   + 從名為 `OriginAccessIdentity` 的欄位中移除值(如果存在)。
   + 將 `ETag` 欄位重新命名為 `IfMatch`，但不要變更欄位的值。

   完成後儲存檔案。

1. 使用下列命令來更新分佈，以使用原始存取控制。

   ```
   aws cloudfront update-distribution --id <CloudFront distribution ID> --cli-input-yaml file://dist-config.yaml
   ```

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 MediaPackage v2 原始伺服器的所有請求。

------
#### [ API ]

如要使用 CloudFront API 建立 OAC，請使用 [CreateOriginAccessControl](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateOriginAccessControl.html)。如需您在此 API 呼叫中指定欄位的詳細資訊，請參閱 AWS SDK 或其他 API 用戶端的 API 參考文件。

建立 OAC 之後，您可以使用下列其中一個 API 呼叫，將其連接至分佈中的 MediaPackage v2 原始伺服器：
+ 如要將其附加至現有分佈中，請使用 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。
+ 如要將其附加至新分佈中，請使用 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html)。

對於這兩個 API 呼叫，請於原始伺服器內部的 `OriginAccessControlId` 欄位中提供 OAC ID。如需您在這些 API 呼叫中指定之其他欄位的詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md)和 AWS SDK 或其他 API 用戶端的 API 參考文件。

------

## 原始存取控制的進階設定
<a name="oac-advanced-settings-mediapackage"></a>

CloudFront OAC 功能包含僅適用於特定使用案例的進階設定。除非您對進階設定有特定需求，否則請使用建議的設定。

OAC 包含名為**簽署行為** （在主控台中） 或 `SigningBehavior`（在 API、CLI 和 中） 的設定 CloudFormation。此設定提供下列選項：

**永遠簽署原始請求 (建議設定)**  
我們建議使用此設定，於主控台中名為**Sign requests (recommended)** (簽署請求 (建議使用))，或於 API、CLI 和 CloudFormation中的 `always`。使用此設定時，CloudFront 一律會簽署傳送至 MediaPackage v2 原始伺服器的所有請求。

**絕不簽署原始伺服器請求**  
此設定於主控台中命名為 **Do not sign requests** (請勿簽署請求)，或 API、CLI 和 CloudFormation中的 `never`。使用此設定，關閉使用此 OAC 之所有分佈中的所有原始伺服器的 OAC。與從所有使用其原始伺服器和分佈中逐一移除 OAC 相比，此可節省時間和精力。使用此設定時，CloudFront 不會簽署傳送至 MediaPackage v2 原始伺服器的任何請求。  
如要使用此設定，MediaPackage v2 原始伺服器必須可公開存取。如果您對無法公開存取的 MediaPackage v2 原始伺服器使用此設定，CloudFront 將無法存取該原始伺服器。MediaPackage v2 原始伺服器會將錯誤傳回 CloudFront，而 CloudFront 會將這些錯誤傳遞給檢視器。如需詳細資訊，請參閱《*AWS Elemental MediaPackage 使用者指南*》中的[適用於 MediaPackage 中政策和許可](https://docs.aws.amazon.com/mediapackage/latest/userguide/policies-permissions.html)的 MediaPackage v2 政策範例。

**請勿覆寫檢視器 (用戶端) `Authorization` 標題**  
此設定於主控台中命名為 **Do not override authorization header** (請勿覆寫授權標頭)，或於 API、CLI 和 CloudFormation中的 `no-override`。如果您想要 CloudFront 僅於對應的檢視器請求不包含 `Authorization` 標題時簽署原始伺服器請求，請使用此設定。利用此設定，當檢視器請求存在時，CloudFront 會傳遞來自檢視器請求的 `Authorization` 標題，但在檢視器請求不包含 `Authorization` 標題時對原始伺服器請求進行簽名 (新增其自己的 `Authorization` 標題)。  
如要從檢視器請求傳遞 `Authorization` 標題，您*必須*將 `Authorization` 標題新增至[快取政策](controlling-the-cache-key.md)中，適用於使用與此原始存取控制相關聯之 MediaPackage v2 原始伺服器的所有快取行為。

# 限制對 AWS Elemental MediaStore 原始伺服器的存取
<a name="private-content-restricting-access-to-mediastore"></a>

CloudFront 提供*原始存取控制* (OAC)，以限制對 AWS Elemental MediaStore 原始伺服器的存取。

**Topics**
+ [建立新的原始存取控制](#create-oac-overview-mediastore)
+ [原始存取控制的進階設定](#oac-advanced-settings-mediastore)

## 建立新的原始存取控制
<a name="create-oac-overview-mediastore"></a>

完成下列主題中說明的步驟，在 CloudFront 中設定新的原始存取控制。

**Topics**
+ [先決條件](#oac-prerequisites-mediastore)
+ [授予 CloudFront 存取 MediaStore 原始伺服器的許可](#oac-permission-to-access-mediastore)
+ [建立原始存取控制](#create-oac-mediastore)

### 先決條件
<a name="oac-prerequisites-mediastore"></a>

在建立和設定原始存取控制之前，您必須擁有具 MediaStore 原始伺服器的 CloudFront 分佈。

### 授予 CloudFront 存取 MediaStore 原始伺服器的許可
<a name="oac-permission-to-access-mediastore"></a>

在您建立原始存取控制或於 CloudFront 分佈中進行設定之前，請確定 CloudFront 具有存取 MediaStore 原始伺服器的許可。在建立 CloudFront 分佈之後，但在將 OAC 新增至分佈組態中的 MediaStore 原始伺服器之前，請執行此作業。

使用 MediaStore 容器政策允許 CloudFront 服務主體 (`cloudfront.amazonaws.com`) 存取原始伺服器。使用政策中的 `Condition` 元素，僅當請求代表包含 S3 原始伺服器的 CloudFront 分佈時，才允許 CloudFront 存取 MediaStore 容器。這是您要新增 OAC 的 MediaStore 原始伺服器分佈。

下列是允許 CloudFront 分佈存取 MediaStore 原始伺服器的 MediaStore 容器政策範例。

**Example MediaStore 容器政策，允許啟用 OAC 之 CloudFront 分佈的唯讀存取**    
****  

```
{
        "Version":"2012-10-17",		 	 	 
        "Statement": [
            {
                "Sid": "AllowCloudFrontServicePrincipalReadOnly",
                "Effect": "Allow",
                "Principal": {
                  "Service": "cloudfront.amazonaws.com"
                },
                "Action": [ 
                  "mediastore:GetObject"
                ],
                "Resource": "arn:aws:mediastore:us-east-1:111122223333:container/<container name>/*",
                "Condition": {
                    "StringEquals": {
                      "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront-distribution-ID"
                    },
                    "Bool": {
                      "aws:SecureTransport": "true"
                    }
                }
            }
        ]
}
```

**Example MediaStore 容器政策，允許啟用 OAC 之 CloudFront 分佈的讀寫存取**    
****  

```
{
        "Version":"2012-10-17",		 	 	 
        "Statement": [
            {
                "Sid": "AllowCloudFrontServicePrincipalReadWrite",
                "Effect": "Allow",
                "Principal": {
                  "Service": "cloudfront.amazonaws.com"
                },
                "Action": [ 
                  "mediastore:GetObject",
                  "mediastore:PutObject"
                ],
                "Resource": "arn:aws:mediastore:us-east-1:111122223333:container/container-name/*",
                "Condition": {
                    "StringEquals": {
                      "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront-distribution-ID"
                    },
                    "Bool": {
                      "aws:SecureTransport": "true"
                    }
                }
            }
        ]
}
```

**注意**  
若要允許寫入存取權，您必須設定 **Allowed HTTP methods** (允許的 HTTP 方法)，以將 `PUT` 包含在 CloudFront 分發的行為設定中。

### 建立原始存取控制
<a name="create-oac-mediastore"></a>

若要建立 OAC，您可以使用 AWS 管理主控台 CloudFormation、 AWS CLI、 或 CloudFront API。

------
#### [ Console ]

**如要建立原始存取控制**

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 於左側導覽窗格中，選擇 **Origin access** (原始存取)。

1. 選擇 **Create control setting** (建立控制設定)。

1. 在 **Create control setting** (建立控制設定) 表單上，執行下列動作：

   1. 於 **Details** (詳細資訊) 窗格中，輸入 **Name** (名稱) 和 (選用) **Description** (描述)，以用於原始存取控制。

   1. 於 **Settings** (設定) 窗格中，建議您保留預設設定 (**Sign requests (recommended)**) (簽署請求 (建議使用))。如需詳細資訊，請參閱[原始存取控制的進階設定](#oac-advanced-settings-mediastore)。

1. 從 **Origin type** (原始伺服器類型) 下拉式功能表中選擇 MediaStore。

1. 選擇**建立**。

   建立 OAC 之後，請記下 **Name** (名稱)。您需要於下列程序中進行使用。

**如要將原始存取控制新增至分佈中的 MediaStore 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇一個您想要新增 OAC 之具 MediaStore 原始伺服器的分佈，然後選擇 **Origins** (原始伺服器) 標籤。

1. 選取您想要將 OAC 新增至的 MediaStore 原始伺服器，然後選擇 **Edit** (編輯)。

1. 在原始伺服器的**Protocol** (通訊協定) 選取 **HTTPS only** (僅限 HTTPS)。

1. 在 **Origin access control** (原始存取控制) 下拉式功能表中，選擇您想要使用的 OAC。

1. 選擇**儲存變更**。

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 MediaStore 儲存貯體原始伺服器的所有請求。

------
#### [ CloudFormation ]

若要使用 建立原始存取控制 (OAC) CloudFormation，請使用 `AWS::CloudFront::OriginAccessControl` 資源類型。下列範例顯示 YAML 格式的 CloudFormation 範本語法，用於建立原始存取控制。

```
Type: AWS::CloudFront::OriginAccessControl
Properties: 
  OriginAccessControlConfig: 
      Description: An optional description for the origin access control
      Name: ExampleOAC
      OriginAccessControlOriginType: mediastore
      SigningBehavior: always
      SigningProtocol: sigv4
```

如需詳細資訊，請參閱《*AWS CloudFormation 使用者指南*》中的 [AWS::CloudFront::OriginAccessControl](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html)。

------
#### [ CLI ]

若要使用 AWS Command Line Interface (AWS CLI) 建立原始存取控制，請使用 **aws cloudfront create-origin-access-control**命令。您可以使用輸入檔案來提供命令的輸入參數，而不必分別將每個個別參數指定為命令列輸入。

**如要建立原始存取控制 (包含輸入檔案的 CLI)**

1. 使用下列命令建立名為 `origin-access-control.yaml` 的檔案。這個檔案中包含 **create-origin-access-control** 命令的所有輸入參數。

   ```
   aws cloudfront create-origin-access-control --generate-cli-skeleton yaml-input > origin-access-control.yaml
   ```

1. 開啟您剛才建立的 `origin-access-control.yaml` 檔案。編輯檔案以新增 OAC 的名稱、說明 (選用)，並將 `SigningBehavior` 變更為 `always`。接著儲存檔案。

   如需其他 OAC 設定的相關資訊，請參閱 [原始存取控制的進階設定](#oac-advanced-settings-mediastore)。

1. 使用下列命令，利用 `origin-access-control.yaml` 檔案中的輸入參數建立原始存取控制。

   ```
   aws cloudfront create-origin-access-control --cli-input-yaml file://origin-access-control.yaml
   ```

   記下命令輸出中的 `Id` 值，您需要其將 OAC 新增至 CloudFront 分佈中的 MediaStore 原始伺服器。

**如要將 OAC 附加至現有分佈 (包含輸入檔案的 CLI) 中的 MediaStore 原始伺服器**

1. 使用下列命令來儲存您想要新增之 CloudFront 分佈的分佈組態。分佈必須具有 MediaStore 原始伺服器。

   ```
   aws cloudfront get-distribution-config --id <CloudFront distribution ID> --output yaml > dist-config.yaml
   ```

1. 開啟您剛才建立且命名為 `dist-config.yaml` 的檔案。編輯檔案，進行下列變更：
   + 於 `Origins` 物件中，將 OAC 的 ID 新增至名為 `OriginAccessControlId` 的欄位。
   + 從名為 `OriginAccessIdentity` 的欄位中移除值(如果存在)。
   + 將 `ETag` 欄位重新命名為 `IfMatch`，但不要變更欄位的值。

   完成後儲存檔案。

1. 使用下列命令來更新分佈，以使用原始存取控制。

   ```
   aws cloudfront update-distribution --id <CloudFront distribution ID> --cli-input-yaml file://dist-config.yaml
   ```

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 MediaStore 原始伺服器的所有請求。

------
#### [ API ]

如要使用 CloudFront API 建立原始存取控制，請使用 [CreateOriginAccessControl](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateOriginAccessControl.html)。如需您在此 API 呼叫中指定欄位的詳細資訊，請參閱 AWS SDK 或其他 API 用戶端的 API 參考文件。

建立原始存取控制之後，您可以使用下列其中一個 API 呼叫，將其連接至分佈中的 MediaStore 原始伺服器：
+ 如要將其附加至現有分佈中，請使用 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。
+ 如要將其附加至新分佈中，請使用 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html)。

對於這兩個 API 呼叫，請於原始伺服器內部的 `OriginAccessControlId` 欄位中提供原始存取控制 ID。如需您在這些 API 呼叫中指定之其他欄位的詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md)和 AWS SDK 或其他 API 用戶端的 API 參考文件。

------

## 原始存取控制的進階設定
<a name="oac-advanced-settings-mediastore"></a>

CloudFront 來原始存取控制功能包含僅適用於特定使用案例的進階設定。除非您對進階設定有特定需求，否則請使用建議的設定。

原始存取控制包含名為**簽署行為** （在主控台中） 或 `SigningBehavior`（在 API、CLI 和 中） 的設定 CloudFormation。此設定提供下列選項：

**永遠簽署原始請求 (建議設定)**  
我們建議使用此設定，於主控台中名為**Sign requests (recommended)** (簽署請求 (建議使用))，或於 API、CLI 和 CloudFormation中的 `always`。使用此設定時，CloudFront 一律會簽署傳送至 MediaStore 原始伺服器的所有請求。

**絕不簽署原始伺服器請求**  
此設定於主控台中命名為 **Do not sign requests** (請勿簽署請求)，或 API、CLI 和 CloudFormation中的 `never`。使用此設定，關閉使用此原始存取控制之所有分佈中的所有原始伺服器的原始存取控制。與從所有使用其原始伺服器和分佈中逐一移除原始存取控制相比，此可節省時間和精力。使用此設定時，CloudFront 不會簽署傳送至 MediaStore 原始伺服器的任何請求。  
如要使用此設定，MediaStore 原始伺服器必須可公開存取。如果您對無法公開存取的 MediaStore 原始伺服器使用此設定，CloudFront 將無法存取該原始伺服器。MediaStore 原始伺服器會將錯誤傳回 CloudFront，而 CloudFront 會將這些錯誤傳遞給檢視器。如需詳細資訊，請參閱[透過 HTTPS 的公有讀取存取](https://docs.aws.amazon.com/mediastore/latest/ug/policies-examples-public-https.html)的 MediaStore 容器政策範例。

**請勿覆寫檢視器 (用戶端) `Authorization` 標題**  
此設定於主控台中命名為 **Do not override authorization header** (請勿覆寫授權標頭)，或於 API、CLI 和 CloudFormation中的 `no-override`。如果您想要 CloudFront 僅於對應的檢視器請求不包含 `Authorization` 標題時簽署原始伺服器請求，請使用此設定。利用此設定，當檢視器請求存在時，CloudFront 會傳遞來自檢視器請求的 `Authorization` 標題，但在檢視器請求不包含 `Authorization` 標題時對原始伺服器請求進行簽名 (新增其自己的 `Authorization` 標題)。  
如要從檢視器請求傳遞 `Authorization` 標題，您*必須*將 `Authorization` 標題新增至[快取政策](controlling-the-cache-key.md)中，適用於使用與此原始存取控制相關聯之 MediaStore 原始伺服器的所有快取行為。

# 限制對 AWS Lambda 函數 URL 原始伺服器的存取
<a name="private-content-restricting-access-to-lambda"></a>

CloudFront 提供*原始存取控制* (OAC)，以限制對 Lambda 函數 URL 原始伺服器的存取。

**Topics**
+ [建立新的 OAC](#create-oac-overview-lambda)
+ [原始存取控制的進階設定](#oac-advanced-settings-lambda)
+ [範本程式碼範例](#example-template-code-lambda-oac)

## 建立新的 OAC
<a name="create-oac-overview-lambda"></a>

完成下列主題中說明的步驟，在 CloudFront 中設定新的 OAC。

**重要**  
如果您搭配 Lambda 函數 URL 使用 `PUT` 或 `POST` 方法，您的使用者必須運算內文的 SHA256，並在將請求傳送至 CloudFront 時，在 `x-amz-content-sha256` 標頭中包含請求內文的承載雜湊值。Lambda 不支援未簽署的承載。

**Topics**
+ [先決條件](#oac-prerequisites-lambda)
+ [授予 CloudFront 存取 Lambda 函數 URL 的許可](#oac-permission-to-access-lambda)
+ [建立 OAC](#create-oac-lambda)

### 先決條件
<a name="oac-prerequisites-lambda"></a>

在建立和設定 OAC 之前，您必須擁有具有 Lambda 函數 URL 做為原始伺服器的 CloudFront 分佈。若要使用 OAC，您必須指定 `AWS_IAM` 作為 `AuthType` 參數的值。如需詳細資訊，請參閱[使用 Lambda 函數 URL](DownloadDistS3AndCustomOrigins.md#concept_lambda_function_url)。

### 授予 CloudFront 存取 Lambda 函數 URL 的許可
<a name="oac-permission-to-access-lambda"></a>

在您建立 OAC 或在 CloudFront 分佈中設定它之前，請確定 CloudFront 具有存取 Lambda 函數 URL 的許可。在建立 CloudFront 分佈之後，但在將 OAC 新增至分佈組態中的 Lambda 函數 URL 之前，請執行此作業。

**注意**  
若要更新 Lambda 函數 URL 的 IAM 政策，您必須使用 AWS Command Line Interface (AWS CLI)。目前不支援在 Lambda 主控台中編輯 IAM 政策。

下列 AWS CLI 命令會授予 CloudFront 服務主體 (`cloudfront.amazonaws.com`) 存取 Lambda 函數 URL 的權限。使用政策中的 `Condition` 元素，*僅*當請求代表包含 Lambda 函數 URL 的 CloudFront 分佈時，才允許 CloudFront 存取 Lambda。這是您要新增 OAC 的 Lambda 函數 URL 原始伺服器分佈。

**Example ： AWS CLI 命令更新政策，以允許啟用 OAC 之 CloudFront 分佈的唯讀存取**  
下列 AWS CLI 命令允許 CloudFront 分佈 (`E1PDK09ESKHJWT`) 存取您的 Lambda *`FUNCTION_URL_NAME`*。

```
aws lambda add-permission \
--statement-id "AllowCloudFrontServicePrincipal" \
--action "lambda:InvokeFunctionUrl" \
--principal "cloudfront.amazonaws.com" \
--source-arn "arn:aws:cloudfront::123456789012:distribution/E1PDK09ESKHJWT" \
--function-name FUNCTION_URL_NAME
```

```
aws lambda add-permission \
--statement-id "AllowCloudFrontServicePrincipalInvokeFunction" \
--action "lambda:InvokeFunction" \
--principal "cloudfront.amazonaws.com" \
--source-arn "arn:aws:cloudfront::123456789012:distribution/E1PDK09ESKHJWT" \
--function-name FUNCTION_URL_NAME
```

**注意**  
如果您建立分佈且沒有 Lambda 函數 URL 的許可，您可以從 CloudFront 主控台選擇**複製 CLI 命令**，然後從命令列終端機輸入此命令。如需詳細資訊，請參閱 *AWS Lambda 開發人員指南*中的[授予函數對 AWS 服務的存取](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-serviceinvoke)。

### 建立 OAC
<a name="create-oac-lambda"></a>

若要建立 OAC，您可以使用 AWS 管理主控台 CloudFormation、 AWS CLI、 或 CloudFront API。

------
#### [ Console ]

**建立 OAC**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 於左側導覽窗格中，選擇 **Origin access** (原始存取)。

1. 選擇 **Create control setting** (建立控制設定)。

1. 在**建立新 OAC** 表單上，執行下列操作：

   1. 輸入 OAC 的**名稱**，(選用) 輸入**描述**。

   1. 於**簽署行為**中，建議您保留預設設定 (**簽署請求 (建議使用)**)。如需詳細資訊，請參閱[原始存取控制的進階設定](#oac-advanced-settings-lambda)。

1. 在**原始伺服器類型**中，選擇 **Lambda**。

1. 選擇**建立**。
**提示**  
建立 OAC 之後，請記下**名稱**。您需要於下列程序中進行使用。

**將原始存取控制新增至分佈中的 Lambda 函數 URL**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇一個您想要新增 OAC 之具 Lambda 函數 URL 的分佈，然後選擇**原始伺服器**標籤。

1. 選取您想要將 OAC 新增至的 Lambda 函數 URL，然後選擇**編輯**。

1. 在原始伺服器的**Protocol** (通訊協定) 選取 **HTTPS only** (僅限 HTTPS)。

1. 在**原始存取控制**下拉式功能表中，選擇您想要使用的 OAC 名稱。

1. 選擇**儲存變更**。

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 Lambda 函數 URL 的所有請求。

------
#### [ CloudFormation ]

若要使用 建立 OAC CloudFormation，請使用 `AWS::CloudFront::OriginAccessControl` 資源類型。下列範例顯示用於建立 OAC 的 YAML 格式 CloudFormation 範本語法。

```
Type: AWS::CloudFront::OriginAccessControl
Properties: 
  OriginAccessControlConfig: 
      Description: An optional description for the origin access control
      Name: ExampleOAC
      OriginAccessControlOriginType: lambda
      SigningBehavior: always
      SigningProtocol: sigv4
```

如需詳細資訊，請參閱《*AWS CloudFormation 使用者指南*》中的 [AWS::CloudFront::OriginAccessControl](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html)。

------
#### [ CLI ]

若要使用 AWS Command Line Interface (AWS CLI) 建立原始存取控制，請使用 **aws cloudfront create-origin-access-control**命令。您可以使用輸入檔案來提供命令的輸入參數，而不必分別將每個個別參數指定為命令列輸入。

**如要建立原始存取控制 (包含輸入檔案的 CLI)**

1. 使用下列命令建立名為 `origin-access-control.yaml` 的檔案。這個檔案中包含 **create-origin-access-control** 命令的所有輸入參數。

   ```
   aws cloudfront create-origin-access-control --generate-cli-skeleton yaml-input > origin-access-control.yaml
   ```

1. 開啟您剛才建立的 `origin-access-control.yaml` 檔案。編輯檔案以新增 OAC 的名稱、說明 (選用)，並將 `SigningBehavior` 變更為 `always`。接著儲存檔案。

   如需其他 OAC 設定的相關資訊，請參閱 [原始存取控制的進階設定](#oac-advanced-settings-lambda)。

1. 使用下列命令，利用 `origin-access-control.yaml` 檔案中的輸入參數建立原始存取控制。

   ```
   aws cloudfront create-origin-access-control --cli-input-yaml file://origin-access-control.yaml
   ```

   記下命令輸出中的 `Id` 值，您需要其將 OAC 新增至 CloudFront 分佈中的 Lambda 函數 URL。

**如要將 OAC 附加至現有分佈 (包含輸入檔案的 CLI) 中的 Lambda 函數 URL**

1. 使用下列命令來儲存您想要新增之 CloudFront 分佈的分佈組態。分佈必須有 Lambda 函數 URL 做為原始伺服器。

   ```
   aws cloudfront get-distribution-config --id <CloudFront distribution ID> --output yaml > dist-config.yaml
   ```

1. 開啟您剛才建立且命名為 `dist-config.yaml` 的檔案。編輯檔案，進行下列變更：
   + 於 `Origins` 物件中，將 OAC 的 ID 新增至名為 `OriginAccessControlId` 的欄位。
   + 從名為 `OriginAccessIdentity` 的欄位中移除值(如果存在)。
   + 將 `ETag` 欄位重新命名為 `IfMatch`，但不要變更欄位的值。

   完成後儲存檔案。

1. 使用下列命令來更新分佈，以使用原始存取控制。

   ```
   aws cloudfront update-distribution --id <CloudFront distribution ID> --cli-input-yaml file://dist-config.yaml
   ```

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 Lambda 函數 URL 的所有請求。

------
#### [ API ]

如要使用 CloudFront API 建立 OAC，請使用 [CreateOriginAccessControl](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateOriginAccessControl.html)。如需您在此 API 呼叫中指定欄位的詳細資訊，請參閱 AWS SDK 或其他 API 用戶端的 API 參考文件。

建立原始存取控制之後，您可以使用下列其中一個 API 呼叫，將其連接至分佈中的 Lambda 函數 URL：
+ 如要將其附加至現有分佈中，請使用 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。
+ 如要將其附加至新分佈中，請使用 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html)。

對於這兩個 API 呼叫，請於原始伺服器內部的 `OriginAccessControlId` 欄位中提供 OAC ID。如需您在這些 API 呼叫中指定之其他欄位的詳細資訊，請參閱 和 AWS SDK 或其他 API 用戶端的 API 參考文件。

------

## 原始存取控制的進階設定
<a name="oac-advanced-settings-lambda"></a>

CloudFront OAC 功能包含僅適用於特定使用案例的進階設定。除非您對進階設定有特定需求，否則請使用建議的設定。

OAC 包含名為**簽署行為** （在主控台中） 或 `SigningBehavior`（在 API、CLI 和 中） 的設定 CloudFormation。此設定提供下列選項：

**永遠簽署原始請求 (建議設定)**  
我們建議使用此設定，於主控台中名為**Sign requests (recommended)** (簽署請求 (建議使用))，或於 API、CLI 和 CloudFormation中的 `always`。使用此設定時，CloudFront 一律會簽署傳送至 Lambda 函數 URL 的所有請求。

**絕不簽署原始伺服器請求**  
此設定於主控台中命名為 **Do not sign requests** (請勿簽署請求)，或 API、CLI 和 CloudFormation中的 `never`。使用此設定，關閉使用此 OAC 之所有分佈中的所有原始伺服器的 OAC。與從所有使用其原始伺服器和分佈中逐一移除 OAC 相比，此可節省時間和精力。使用此設定時，CloudFront 不會簽署傳送至 Lambda 函數 URL 的任何請求。  
若要使用此設定，Lambda 函數 URL 必須可公開存取。如果您對無法公開存取的 Lambda 函數 URL 使用此設定，CloudFront 將無法存取該原始伺服器。Lambda 函數 URL 會將錯誤傳回 CloudFront，而 CloudFront 會將這些錯誤傳遞給檢視器。如需詳細資訊，請參閱 *AWS Lambda 使用者指南*中的 [Lambda 函數 URL 的安全性和驗證模型](https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html)。

**請勿覆寫檢視器 (用戶端) `Authorization` 標題**  
此設定於主控台中命名為 **Do not override authorization header** (請勿覆寫授權標頭)，或於 API、CLI 和 CloudFormation中的 `no-override`。如果您想要 CloudFront 僅於對應的檢視器請求不包含 `Authorization` 標題時簽署原始伺服器請求，請使用此設定。利用此設定，當檢視器請求存在時，CloudFront 會傳遞來自檢視器請求的 `Authorization` 標題，但在檢視器請求不包含 `Authorization` 標題時對原始伺服器請求進行簽名 (新增其自己的 `Authorization` 標題)。  
+ 如果您使用此設定，則必須為 Lambda 函數 URL 指定簽章第 4 版簽署，而不是 CloudFront 分佈的名稱或 CNAME。當 CloudFront 將 `Authorization` 標頭從檢視器請求轉送至 Lambda 函數 URL 時，Lambda 會根據 Lambda URL 網域的主機驗證簽署。如果簽署不是以 Lambda URL 網域為基礎，則簽署中的主機與 Lambda URL 原始伺服器所使用的主機不相符。這表示請求將會失敗，導致簽署驗證錯誤。
+ 如要從檢視器請求傳遞 `Authorization` 標題，您*必須*將 `Authorization` 標題新增至[快取政策](controlling-the-cache-key.md)中，適用於使用與此原始存取控制相關聯之 Lambda 函數 URL 的所有快取行為。

## 範本程式碼範例
<a name="example-template-code-lambda-oac"></a>

如果您的 CloudFront 原始伺服器是與 OAC 相關聯的 Lambda 函數 URL，您可以使用下列 Python 指令碼，透過 `POST` 方法將檔案上傳至 Lambda 函數。

此程式碼假設您已將預設簽署行為設定為**永遠簽署原始請求**的 OAC，且未選取**請勿覆寫授權標頭**設定。

此組態允許 OAC 使用 Lambda 主機名稱，以 Lambda 正確管理 SigV4 授權。承載是從 Lambda 函數 URL 授權的 IAM 身分使用 SigV4 簽署，該身分指定為 `IAM_AUTH` 類型。

範本示範如何處理來自用戶端 `POST` 請求的 x-amz-content-sha256 標頭中簽署的承載雜湊值。具體而言，此範本旨在管理表單資料承載。範本可透過 CloudFront 將安全檔案上傳至 Lambda 函數 URL，並使用 AWS 身分驗證機制來確保只有授權的請求才能存取 Lambda 函數。

**程式碼包含下列功能：**  
符合在 x-amz-content-sha256 標頭中包含承載雜湊的需求
使用 SigV4 身分驗證進行安全 AWS 服務 存取
支援使用分段表單資料上傳檔案
包含請求例外狀況的錯誤處理

```
import boto3
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
import requests
import hashlib
import os


def calculate_body_hash(body):
    return hashlib.sha256(body).hexdigest()


def sign_request(request, credentials, region, service):
    sigv4 = SigV4Auth(credentials, service, region)
    sigv4.add_auth(request)


def upload_file_to_lambda(cloudfront_url, file_path, region):
    # AWS credentials
    session = boto3.Session()
    credentials = session.get_credentials()

    # Prepare the multipart form-data
    boundary = "------------------------boundary"

    # Read file content
    with open(file_path, 'rb') as file:
        file_content = file.read()

    # Get the filename from the path
    filename = os.path.basename(file_path)

    # Prepare the multipart body
    body = (
        f'--{boundary}\r\n'
        f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n'
        f'Content-Type: application/octet-stream\r\n\r\n'
    ).encode('utf-8')
    body += file_content
    body += f'\r\n--{boundary}--\r\n'.encode('utf-8')

    # Calculate SHA256 hash of the entire body
    body_hash = calculate_body_hash(body)

    # Prepare headers
    headers = {
        'Content-Type': f'multipart/form-data; boundary={boundary}',
        'x-amz-content-sha256': body_hash
    }

    # Create the request
    request = AWSRequest(
        method='POST',
        url=cloudfront_url,
        data=body,
        headers=headers
    )

    # Sign the request
    sign_request(request, credentials, region, 'lambda')

    # Get the signed headers
    signed_headers = dict(request.headers)

    # Print request headers before sending
    print("Request Headers:")
    for header, value in signed_headers.items():
        print(f"{header}: {value}")

    try:
        # Send POST request with signed headers
        response = requests.post(
            cloudfront_url,
            data=body,
            headers=signed_headers
        )

        # Print response status and content
        print(f"\nStatus code: {response.status_code}")
        print("Response:", response.text)

        # Print response headers
        print("\nResponse Headers:")
        for header, value in response.headers.items():
            print(f"{header}: {value}")

    except requests.exceptions.RequestException as e:
        print(f"An error occurred: {e}")


# Usage
cloudfront_url = "https://d111111abcdef8.cloudfront.net"
file_path = r"filepath"
region = "us-east-1"  # example: "us-west-2"

upload_file_to_lambda(cloudfront_url, file_path, region)
```

# 限制對 Amazon S3 原始伺服器的存取
<a name="private-content-restricting-access-to-s3"></a>

CloudFront 提供兩種方式，將驗證請求傳送至 Amazon S3 原始伺服器：*原始存取控制*(OAC) 和*原始存取身分* (OAI)。OAC 可協助您保護原始伺服器，例如 Amazon S3。

*建議*您改用 OAC，因為它支援下列功能：
+ 所有 中的所有 Amazon S3 儲存貯體 AWS 區域，包括 2022 年 12 月之後啟動的選擇加入區域
+ [使用 AWS KMS的 Amazon S3 伺服器端加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html) (SSE-KMS)
+ 對 Amazon S3 的動態請求 (`PUT` 和 `DELETE`)

OAI 不支援這些功能，或在這些案例中需要額外的解決方法。如果您已經在使用 OAI 且想要移轉，請參閱 [從原始存取身分 (OAI) 遷移至原始存取控制 (OAC)](#migrate-from-oai-to-oac)。

**備註**  
當您將 CloudFront OAC 與 Amazon S3 儲存貯體原始伺服器搭配使用時，必須將 **Amazon S3 物件擁有權**設定為**強制執行儲存貯體擁有者**，這是新 Amazon S3 儲存貯體的預設值。如果您需要 ACL，請使用**儲存貯體擁有者偏好**設定來維持透過 CloudFront 上傳之物件的控制權。
如果您使用設定為[網站端點](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html)的 Amazon S3 儲存貯體，則必須使用 CloudFront 將其設定為自訂原始伺服器。這表示您無法使用 OAC (或 OAI)。OAC 不支援使用 Lambda@Edge 的原始伺服器重新導向。
如果您使用 Amazon S3 多區域存取點做為 CloudFront 原始伺服器，請參閱 [限制對 Amazon S3 多區域存取點原始伺服器的存取](private-content-restricting-access-to-s3-mrap.md)。S3 多區域存取點需要不同的 OAC 組態。

下列主題說明如何將 OAC 與 Amazon S3 原始伺服器搭配使用。

**主題**
+ [建立新的原始存取控制](#create-oac-overview-s3)
+ [刪除含附加至 S3 儲存貯體之 OAC 的分佈](#delete-oac-distribution-s3)
+ [從原始存取身分 (OAI) 遷移至原始存取控制 (OAC)](#migrate-from-oai-to-oac)
+ [原始存取控制的進階設定](#oac-advanced-settings-s3)

## 建立新的原始存取控制
<a name="create-oac-overview-s3"></a>

完成下列主題中說明的步驟，在 CloudFront 中設定新的原始存取控制。

**Topics**
+ [先決條件](#oac-prerequisites-s3)
+ [授予 CloudFront 存取 S3 儲存貯體的許可](#oac-permission-to-access-s3)
+ [建立原始存取控制](#create-oac-s3)

### 先決條件
<a name="oac-prerequisites-s3"></a>

在建立和設定原始存取控制 (OAC) 之前，您必須擁有具 Amazon S3 儲存貯體原始伺服器的 CloudFront 分佈。此原始伺服器必須是一般 S3 儲存貯體，而非設定為[網站端點](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html)的儲存貯體。如需使用 S3 儲存貯體原始伺服器設定 CloudFront 分佈的相關資訊，請參閱 [開始使用 CloudFront 標準分佈](GettingStarted.SimpleDistribution.md)。

**重要**  
當您使用 OAC 來保護 Amazon S3 原始伺服器時，CloudFront 和 Amazon S3 之間的通訊*一律*透過 HTTPS 進行，但前提是您選擇*一律簽署請求*。您必須在主控台中選擇**簽署請求 （建議）**，或在 CloudFront API AWS CLI或 CloudFormation `always`中指定 。  
如果您選擇**不簽署請求**或**不覆寫授權標頭**選項，CloudFront 會使用您在下列政策中指定的連線通訊協定：  
[檢視器通訊協定政策](using-https-viewers-to-cloudfront.md) 
[原始伺服器通訊協定政策](DownloadDistValuesOrigin.md#DownloadDistValuesOriginProtocolPolicy) (僅限自訂原始伺服器)
例如，如果您選擇**不要覆寫授權標頭**，並想要在 CloudFront 和 Amazon S3 原始伺服器之間使用 HTTPS，請僅針對[檢視器通訊協定政策](using-https-viewers-to-cloudfront.md)使用**重新導向 HTTP 至 HTTPS** 或**僅限 HTTPS**。

### 授予 CloudFront 存取 S3 儲存貯體的許可
<a name="oac-permission-to-access-s3"></a>

在您建立原始存取控制 (OAC) 或於 CloudFront 分佈中進行設定之前，請確定 CloudFront 具有存取 S3 儲存貯體原始伺服器的許可。在建立 CloudFront 分佈之後，但在將 OAC 新增至分佈組態中的 S3 原始伺服器之前，請執行此作業。

使用 [S3 儲存貯體政策](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html)允許 CloudFront 服務主體 (`cloudfront.amazonaws.com`) 存取儲存貯體。使用政策中的 `Condition` 元素，僅當請求代表包含 S3 原始伺服器的 CloudFront 分佈時，才允許 CloudFront 存取儲存貯體。這是您要新增 OAC 的 S3 原始伺服器分佈。

如需新增或修改儲存貯體政策的相關資訊，請參閱 [Amazon S3 使用者指南](https://docs.aws.amazon.com/AmazonS3/latest/userguide/add-bucket-policy.html)中的*使用 Amazon S3 主控台新增儲存貯體政策*。

下列是允許啟用 OAC 之 CloudFront 分佈存取 S3 原始伺服器的 S3 儲存貯體政策範例。

**Example S3 儲存貯體政策，允許啟用 OAC 之 CloudFront 分佈的唯讀存取**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipalReadOnly",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/<CloudFront distribution ID>"
        }
      }
    }
  ]
}
```

**Example S3 儲存貯體政策，允許啟用 OAC 之 CloudFront 分佈的讀寫存取**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipalReadWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront-distribution-ID>"
        }
      }
    }
  ]
}
```

#### SSE-KMS
<a name="oac-permissions-sse-kms"></a>

如果使用[伺服器端加密搭配 AWS Key Management Service (SSE-KMS) 來加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html) S3 儲存貯體原始伺服器中的物件，您必須確保 CloudFront 分佈具有使用 AWS KMS 金鑰的許可。如要授予 CloudFront 分佈使用 KMS 金鑰的許可，請將陳述式新增至 [KMS 金鑰政策](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)。如需如何修改金鑰政策的相關資訊，請參閱《*AWS Key Management Service 開發人員指南*》中的[變更金鑰政策](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying.html)。

**Example KMS 金鑰政策陳述式**  
下列範例顯示 AWS KMS 政策陳述式，允許具有 OAC 的 CloudFront 分佈存取 SSE-KMS 的 KMS 金鑰。  

```
{
    "Sid": "AllowCloudFrontServicePrincipalSSE-KMS",
    "Effect": "Allow",
    "Principal": {
        "Service": [
            "cloudfront.amazonaws.com"
        ]
     },
    "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey*"
    ],
    "Resource": "*",
    "Condition": {
            "StringEquals": {
                "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/<CloudFront distribution ID>"
            }
        }
}
```

### 建立原始存取控制
<a name="create-oac-s3"></a>

若要建立原始存取控制 (OAC) CloudFormation，您可以使用 AWS 管理主控台、 AWS CLI、 或 CloudFront API。

------
#### [ Console ]

**如要建立原始存取控制**

1. 登入 AWS 管理主控台 並開啟位於 的 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 於左側導覽窗格中，選擇 **Origin access** (原始存取)。

1. 選擇 **Create control setting** (建立控制設定)。

1. 在 **Create control setting** (建立控制設定) 表單上，執行下列動作：

   1. 於 **Details** (詳細資訊) 窗格中，輸入 **Name** (名稱) 和 (選用) **Description** (描述)，以用於原始存取控制。

   1. 於 **Settings** (設定) 窗格中，建議您保留預設設定 (**Sign requests (recommended)**) (簽署請求 (建議使用))。如需詳細資訊，請參閱[原始存取控制的進階設定](#oac-advanced-settings-s3)。

1. 從 **Origin type** (原始伺服器類型) 下拉式功能表中選擇 S3。

1. 選擇**建立**。

   建立 OAC 之後，請記下 **Name** (名稱)。您需要於下列程序中進行使用。

**如要將原始存取控制新增至分佈中的 S3 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇一個您想要新增 OAC 之具 S3 原始伺服器的分佈，然後選擇 **Origins** (原始伺服器) 標籤。

1. 選取您想要將 OAC 新增至的 S3 原始伺服器，然後選擇 **Edit** (編輯)。

1. 針對**原始存取**，選擇**原始存取控制設定 (建議使用)**。

1. 在 **Origin access control** (原始存取控制) 下拉式功能表中，選擇您想要使用的 OAC。

1. 選擇**儲存變更**。

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 S3 儲存貯體原始伺服器的所有請求。

------
#### [ CloudFormation ]

若要使用 建立原始存取控制 (OAC) CloudFormation，請使用 `AWS::CloudFront::OriginAccessControl` 資源類型。下列範例顯示 YAML 格式的 CloudFormation 範本語法，用於建立原始存取控制。

```
Type: AWS::CloudFront::OriginAccessControl
Properties: 
  OriginAccessControlConfig: 
      Description: An optional description for the origin access control
      Name: ExampleOAC
      OriginAccessControlOriginType: s3
      SigningBehavior: always
      SigningProtocol: sigv4
```

如需詳細資訊，請參閱《*AWS CloudFormation 使用者指南*》中的 [AWS::CloudFront::OriginAccessControl](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html)。

------
#### [ CLI ]

若要使用 AWS Command Line Interface (AWS CLI) 建立原始存取控制，請使用 **aws cloudfront create-origin-access-control**命令。您可以使用輸入檔案來提供命令的輸入參數，而不必分別將每個個別參數指定為命令列輸入。

**如要建立原始存取控制 (包含輸入檔案的 CLI)**

1. 使用下列命令建立名為 `origin-access-control.yaml` 的檔案。這個檔案中包含 **create-origin-access-control** 命令的所有輸入參數。

   ```
   aws cloudfront create-origin-access-control --generate-cli-skeleton yaml-input > origin-access-control.yaml
   ```

1. 開啟您剛才建立的 `origin-access-control.yaml` 檔案。編輯檔案以新增 OAC 的名稱、說明 (選用)，並將 `SigningBehavior` 變更為 `always`。接著儲存檔案。

   如需其他 OAC 設定的相關資訊，請參閱 [原始存取控制的進階設定](#oac-advanced-settings-s3)。

1. 使用下列命令，利用 `origin-access-control.yaml` 檔案中的輸入參數建立原始存取控制。

   ```
   aws cloudfront create-origin-access-control --cli-input-yaml file://origin-access-control.yaml
   ```

   記下命令輸出中的 `Id` 值，您需要其將 OAC 新增至 CloudFront 分佈中的 S3 儲存貯體原始伺服器。

**如要將 OAC 附加至現有分佈 (包含輸入檔案的 CLI) 中的 S3 儲存貯體原始伺服器**

1. 使用下列命令來儲存您想要新增之 CloudFront 分佈的分佈組態。分佈必須具有 S3 儲存貯體原始伺服器。

   ```
   aws cloudfront get-distribution-config --id <CloudFront distribution ID> --output yaml > dist-config.yaml
   ```

1. 開啟您剛才建立且命名為 `dist-config.yaml` 的檔案。編輯檔案，進行下列變更：
   + 於 `Origins` 物件中，將 OAC 的 ID 新增至名為 `OriginAccessControlId` 的欄位。
   + 從名為 `OriginAccessIdentity` 的欄位中移除值(如果存在)。
   + 將 `ETag` 欄位重新命名為 `IfMatch`，但不要變更欄位的值。

   完成後儲存檔案。

1. 使用下列命令來更新分佈，以使用原始存取控制。

   ```
   aws cloudfront update-distribution --id <CloudFront distribution ID> --cli-input-yaml file://dist-config.yaml
   ```

分佈開始部署至所有 CloudFront 邊緣節點。當邊緣節點接收到新組態時，其會簽署傳送至 S3 儲存貯體原始伺服器的所有請求。

------
#### [ API ]

如要使用 CloudFront API 建立原始存取控制，請使用 [CreateOriginAccessControl](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateOriginAccessControl.html)。如需您在此 API 呼叫中指定欄位的詳細資訊，請參閱 AWS SDK 或其他 API 用戶端的 API 參考文件。

建立原始存取控制之後，您可以使用下列其中一個 API 呼叫，將其連接至分佈中的 S3 儲存貯體原始伺服器：
+ 如要將其附加至現有分佈中，請使用 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。
+ 如要將其附加至新分佈中，請使用 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html)。

對於這兩個 API 呼叫，請於原始伺服器內部的 `OriginAccessControlId` 欄位中提供原始存取控制 ID。如需您在這些 API 呼叫中指定之其他欄位的詳細資訊，請參閱 [所有分佈設定參考](distribution-web-values-specify.md)和 AWS SDK 或其他 API 用戶端的 API 參考文件。

------

## 刪除含附加至 S3 儲存貯體之 OAC 的分佈
<a name="delete-oac-distribution-s3"></a>

如果您需要刪除含附加至 S3 儲存貯體之 OAC 的分佈，您應該先刪除分佈，再刪除 S3 儲存貯體原始伺服器。或者，在原始伺服器網域名稱中包含區域。如果無法這麼做，您可以在刪除之前切換到公有，從分佈中移除 OAC。如需詳細資訊，請參閱[刪除 分發](HowToDeleteDistribution.md)。

## 從原始存取身分 (OAI) 遷移至原始存取控制 (OAC)
<a name="migrate-from-oai-to-oac"></a>

如要從舊式原始存取身分 (OAI) 移轉至原始存取控制 (OAC)，請先更新 S3 儲存貯體原始伺服器，以允許 OAI 和啟用 OAC 之分佈存取儲存貯體的內容。此可確保 CloudFront 在轉換期間永遠不會失去儲存貯體的存取權限。如要允許 OAI 和啟用 OAC 之分佈存取 S3 儲存貯體，請更新[儲存貯體政策](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html)，以包括兩個陳述式，每種主體各一個。

下列範例 S3 儲存貯體政策允許 OAI 和啟用 OAC 之分佈存取 S3 原始伺服器。

**Example 允許對 OAI 和啟用 OAC 之 CloudFront 分佈進行唯讀存取的 S3 儲存貯體政策**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipalReadOnly",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<S3 bucket name>/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/<CloudFront distribution ID>"
                }
            }
        },
        {
            "Sid": "AllowLegacyOAIReadOnly",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <origin access identity ID>"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<S3 bucket name>/*"
        }
    ]
}
```

更新 S3 原始伺服器的儲存貯體政策以允許存取 OAI 和 OAC 之後，您可更新發佈組態以使用 OAC 而非 OAI。如需詳細資訊，請參閱[建立新的原始存取控制](#create-oac-overview-s3)。

完整部署分佈之後，您可移除儲存貯體政策中允許存取 OAI 的陳述式。如需詳細資訊，請參閱[授予 CloudFront 存取 S3 儲存貯體的許可](#oac-permission-to-access-s3)。

## 原始存取控制的進階設定
<a name="oac-advanced-settings-s3"></a>

CloudFront 來原始存取控制功能包含僅適用於特定使用案例的進階設定。除非您對進階設定有特定需求，否則請使用建議的設定。

原始存取控制包含名為**簽署行為** （在主控台中） 或 `SigningBehavior`（在 API、CLI 和 中） 的設定 CloudFormation。此設定提供下列選項：

**永遠簽署原始請求 (建議設定)**  
我們建議使用此設定，於主控台中名為**Sign requests (recommended)** (簽署請求 (建議使用))，或於 API、CLI 和 CloudFormation中的 `always`。使用此設定時，CloudFront 一律會簽署傳送至 S3 儲存貯體原始伺服器的所有請求。

**絕不簽署原始伺服器請求**  
此設定於主控台中命名為 **Do not sign requests** (請勿簽署請求)，或 API、CLI 和 CloudFormation中的 `never`。使用此設定，關閉使用此原始存取控制之所有分佈中的所有原始伺服器的原始存取控制。與從所有使用其原始伺服器和分佈中逐一移除原始存取控制相比，此可節省時間和精力。使用此設定時，CloudFront 不會簽署傳送至 S3 儲存貯體原始伺服器的任何請求。  
如要使用此設定，S3 儲存貯體原始伺服器必須可公開存取。如果您對無法公開存取的 S3 儲存貯體原始伺服器使用此設定，CloudFront 將無法存取該原始伺服器。S3 儲存貯體原始伺服器會將錯誤傳回 CloudFront，而 CloudFront 會將這些錯誤傳遞給檢視器。

**請勿覆寫檢視器 (用戶端) `Authorization` 標題**  
此設定於主控台中命名為 **Do not override authorization header** (請勿覆寫授權標頭)，或於 API、CLI 和 CloudFormation中的 `no-override`。如果您想要 CloudFront 僅於對應的檢視器請求不包含 `Authorization` 標題時簽署原始伺服器請求，請使用此設定。利用此設定，當檢視器請求存在時，CloudFront 會傳遞來自檢視器請求的 `Authorization` 標題，但在檢視器請求不包含 `Authorization` 標題時對原始伺服器請求進行簽名 (新增其自己的 `Authorization` 標題)。  
如要從檢視器請求傳遞 `Authorization` 標題，您*必須*將 `Authorization` 標題新增至[快取政策](controlling-the-cache-key.md)中，適用於使用與此原始存取控制相關聯之 S3 儲存貯體原始伺服器的所有快取行為。

## 使用原始存取身分 (舊版，不建議使用)
<a name="private-content-restricting-access-to-s3-oai"></a>

### 原始存取身分概觀
<a name="private-content-restricting-access-to-s3-overview"></a>

CloudFront*原始存取身分* (OAI) 提供與*原始存取控制* (OAC) 類似的功能，但其不適用於所有案例。具體而言，OAI 不支援：
+ 所有 中的 Amazon S3 儲存貯體 AWS 區域，包括選擇加入區域
+ [使用 AWS KMS的 Amazon S3 伺服器端加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html) (SSE-KMS)
+ 對 Amazon S3 的動態請求 (`PUT`、`POST` 或 `DELETE`)
+ 2023 年 1 月之後 AWS 區域 推出的新功能

**提示**  
我們建議您改用 OAC。若要設定 OAC，請參閱 [建立新的原始存取控制](#create-oac-overview-s3)。如需如何從 OAI 遷移至 OAC 的相關資訊，請參閱 [從原始存取身分 (OAI) 遷移至原始存取控制 (OAC)](#migrate-from-oai-to-oac)。

### 授予原始存取身分的許可，以讀取 Amazon S3 儲存貯體中的檔案
<a name="private-content-granting-permissions-to-oai"></a>

當您使用 CloudFront 主控台建立 OAI 或新增 OAI 至分佈時，您可以自動更新 Amazon S3 儲存貯體政策，讓 OAI 有權存取您的儲存貯體。或者，您可以選擇手動建立或更新儲存貯體政策。無論您使用哪種方法，您仍應檢閱許可以確認下列事項：
+ CloudFront OAI 可以代表透過 CloudFront 請求檔案的檢視器，來存取儲存貯體中的檔案。
+ 檢視器無法使用 Amazon S3 URL 在 CloudFront 之外存取您的檔案。

**重要**  
如果您將 CloudFront 設定為接受和轉送 CloudFront 支援的所有 HTTP 方法，請務必為您的 CloudFront OAI 提供所需的許可。例如，如果您將 CloudFront 設定為接受並轉送使用 `DELETE` 方法的請求，請將儲存貯體政策設定為適當地處理 `DELETE` 請求，讓檢視器只能刪除您希望其刪除的檔案。

#### 使用 Amazon S3 儲存貯體政策
<a name="private-content-updating-s3-bucket-policies"></a>

您可以透過下列方法建立或更新儲存貯體政策，藉此授予 CloudFront OAI 對 Amazon S3 儲存貯體中檔案的存取權限：
+ 使用 [Amazon S3 主控台](https://console.aws.amazon.com/s3/home)中的 Amazon S3 儲存貯體的**Permissions** (許可) 標籤。
+ 在 Amazon S3 API 中使用 [PutBucket 政策](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html)。
+ 使用 [CloudFront 主控台](https://console.aws.amazon.com/cloudfront/v4/home)。當您將 OAI 新增到 CloudFront 主控台中的原始伺服器設定時，您可以選擇 **Yes, update the bucket 政策 (是，更新儲存貯體政策)**，請 CloudFront 代表您更新儲存貯體政策。

如果您手動更新儲存貯體政策，請務必：
+ 在政策中指定正確的 OAI 做為 `Principal`。
+ 授予 OAI 代表檢視器存取物件所需的許可。

如需詳細資訊，請參閱下列區段。

##### 在儲存貯體政策中指定 OAI 做為 `Principal`
<a name="private-content-updating-s3-bucket-policies-principal"></a>

若要於 Amazon S3 儲存貯體政策中指定 OAI 做為 `Principal`，請使用包含 OAI ID 的 OAI Amazon Resource Name (ARN)。例如：

```
"Principal": {
    "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <origin access identity ID>"
}
```

在**安全性**、**原始存取**、**身分 (舊版)** 下的 CloudFront 主控台中尋找 OAI ID。或者，在 CloudFront API 中使用 [ListCloudFrontOriginAccessIdentities](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListCloudFrontOriginAccessIdentities.html)。

##### 授予權限給一個 OAI
<a name="private-content-updating-s3-bucket-policies-permissions"></a>

如要授予 OAI 存取 Amazon S3 儲存貯體中物件的許可，請使用與特定 Amazon S3 API 作業相關政策中的動作。例如，`s3:GetObject` 動作可讓 OAI 讀取儲存貯體中的物件。如需詳細資訊，請參閱以下章節中的範例，或參閱 *Amazon Simple Storage Service 使用者指南*中的 [Amazon S3 動作](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html)。

##### Amazon S3 儲存貯體政策範例
<a name="private-content-updating-s3-bucket-policies-examples"></a>

下列範例顯示允許 CloudFront OAI 存取 S3 儲存貯體的 Amazon S3 儲存貯體政策。

在**安全性**、**原始存取**、**身分 (舊版)** 下的 CloudFront 主控台中尋找 OAI ID。或者，在 CloudFront API 中使用 [ListCloudFrontOriginAccessIdentities](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListCloudFrontOriginAccessIdentities.html)。

**Example 授予 OAI 讀取存取權限的 Amazon S3 儲存貯體政策**  
下列範例可讓 OAI 讀取指定儲存貯體中的物件 (`s3:GetObject`)。    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <origin access identity ID>"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<S3 bucket name>/*"
        }
    ]
}
```

**Example 授予 OAI 讀取和寫入存取權限的 Amazon S3 儲存貯體政策**  
下列範例可讓 OAI 讀取和寫入指定儲存貯體中的物件 (`s3:GetObject` 和 `s3:PutObject`)。這可讓檢視器透過 CloudFront 將檔案上傳到您的 Amazon S3 儲存貯體。    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <origin access identity ID>"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::<S3 bucket name>/*"
        }
    ]
}
```

#### 使用 Amazon S3 物件 ACL (不建議)
<a name="private-content-updating-s3-acls"></a>

**重要**  
我們建議[使用 Amazon S3 儲存貯體政策](#private-content-updating-s3-bucket-policies) 向 OAI 提供 S3 儲存貯體的存取權。您可以使用存取控制清單 (ACL)，如本節中所述，但我們不建議此方法。  
Amazon S3 建議設定 [S3 物件擁有權](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)為**已強制執行儲存貯體擁有者**，這意味著儲存貯體及其中物件的 ACL 被停用。當您將此設定套用至「物件擁有權」 時，您必須使用儲存貯體政策來授與 OAI 的存取權 (請參閱上一節)。  
本節僅適用於需要 ACL 的舊式使用案例。

您可透過下列方法建立或更新檔案的 ACL，藉此授予 CloudFront OAI 對 Amazon S3 儲存貯體中檔案的存取權限：
+ 使用 [Amazon S3 主控台](https://console.aws.amazon.com/s3/home)中 Amazon S3 物件的 **Permissions** (許可) 標籤。
+ 使用 Amazon S3 API 中的 [PutObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectAcl.html)。

當您使用 ACL 授予對 OAI 的存取權限時，您必須使用 OAI 的 Amazon S3 正式使用者 ID 來指定 OAI。在 CloudFront 主控台中，您可以在**安全性**、**原始存取**、**身分 (舊版)** 下找到此 ID。如果您使用的是 CloudFront API，請使用 `S3CanonicalUserId` 元素的值，此元素是在您建立 OAI 或呼叫 CloudFront API 中的 [ListCloudFrontOriginAccessIdentities](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListCloudFrontOriginAccessIdentities.html) 時傳回。

### 在僅支援簽署版本 4 驗證的 Amazon S3 區域中使用原始存取身分
<a name="private-content-origin-access-identity-signature-version-4"></a>

較新 Amazon S3 區域請求您使用簽章版本 4 進行驗證請求 (如需每個 Amazon S3 區域支援的簽署版本，請參閱《*AWS 一般參考*》中的 [Amazon Simple Storage Service 端點和配額](https://docs.aws.amazon.com/general/latest/gr/s3.html)。) 如果您使用的是原始存取身分，且您的儲存貯體位於需要簽章版本 4 的其中一個區域，請注意下列事項：
+ `DELETE`、`GET`、`HEAD`、`OPTIONS` 和 `PATCH` 請求可以在沒有授權的情況下得到支援。
+ 不支援 `POST` 請求。

# 使用 VPC 原始伺服器限制存取
<a name="private-content-vpc-origins"></a>

您可以使用 CloudFront 從虛擬私有雲端 (VPC) 私有子網路中託管的應用程式交付內容。您可以使用 Application Load Balancer (ALB)、Network Load Balancer (NLB) 和私有子網路中的 EC2 執行個體做為 VPC 原始伺服器。

以下是您可能想要使用 VPC 原始伺服器的一些原因：
+ **安全** – VPC 原始伺服器旨在透過將負載平衡器和 EC2 執行個體放置在私有子網路中，使 CloudFront 成為單一進入點，來增強應用程式的安全狀態。使用者請求會透過私有、安全的連線從 CloudFront 轉移到 VPC 原始伺服器，為您的應用程式提供額外的安全性。
+ **管理** – VPC 原始伺服器可減少 CloudFront 與原始伺服器之間安全連線所需的營運開銷。您可以將原始伺服器移至沒有公有存取權的私有子網路，而且您不需要實作存取控制清單 (ACL) 或其他機制來限制對原始伺服器的存取。如此一來，您就不必投資未差異化的開發工作，即可使用 CloudFront 保護您的 Web 應用程式。
+ **可擴展性和效能** – VPC 原始伺服器可協助您保護 Web 應用程式，騰出時間專注於擴展關鍵業務應用程式，同時透過 CloudFront 提高安全性和維護高效能和全球可擴展性。VPC 原始伺服器可簡化安全管理並降低操作複雜性，讓您可以使用 CloudFront 做為應用程式的單一進入點。

**提示**  
CloudFront 支援跨 共用 VPC 原始伺服器 AWS 帳戶，無論它們是否在您的組織中。您可以從 CloudFront 主控台共用 VPC 原始伺服器或使用 AWS Resource Access Manager (AWS RAM)。如需詳細資訊，請參閱[在 CloudFront 中使用共享的資源](sharing-resources.md)。

## 先決條件
<a name="vpc-origin-prerequisites"></a>

為 CloudFront 分佈建立 VPC 原始伺服器之前，您必須完成下列操作：

### VPC 組態
<a name="vpc-configuration"></a>

**在 VPC 原始伺服器支援的其中一個 中，在 Amazon VPC 上建立虛擬私有雲端 (VPC)**。 AWS 區域 如需有關建立 VPC 的資訊，請參閱《*Amazon VPC 使用者指南*》中的[建立 VPC 和其他 VPC 資源](https://docs.aws.amazon.com/vpc/latest/userguide/create-vpc.html#create-vpc-and-other-resources)。如需支援的區域的清單，請參閱 [AWS 區域 支援 VPC 原始伺服器](#vpc-origins-supported-regions)。

您的 VPC 必須包含下列項目：
+ **網際網路閘道** – 您需要將網際網路閘道新增至具有 VPC 原始資源的 VPC。需要網際網路閘道才能表示 VPC 可以從網際網路接收流量。網際網路閘道不會用於將流量路由到子網路內的原始伺服器，而且您不需要更新路由政策。
+ **具有至少一個可用 IPv4 位址的私有子網路** – CloudFront 會使用 CloudFront 在您使用 CloudFront 定義 VPC 原始伺服器資源後建立的服務受管彈性網路介面 (ENI)，路由到您的子網路。您的私有子網路中必須至少有一個可用的 IPv4 位址，以成功完成 ENI 建立程序。IPv4 位址可以是私有位址，而且無需額外費用。不支援 IPv6-only 子網路。

### 原始伺服器資源
<a name="origin-resources"></a>

在私有子網路中，啟動 Application Load Balancer、Network Load Balancer 或 EC2 執行個體以做為原始伺服器。您啟動的資源必須完全部署且處於作用中狀態，才能將其用於 VPC 原始伺服器。

**原始伺服器限制：**
+ Gateway Load Balancer 無法新增為原始伺服器
+ 雙堆疊 Network Load Balancer 無法新增為原始伺服器
+ 具有 TLS 接聽程式的網路負載平衡器無法新增為原始伺服器
+ 若要用作 VPC 原始伺服器，Network Load Balancer 必須連接安全群組

### 安全群組設定
<a name="security-group-configuration"></a>

您的 VPC 原始伺服器資源 (Application Load Balancer、Network Load Balancer 或 EC2 執行個體） 必須連接安全群組。當您建立 VPC 原始伺服器時，CloudFront 會自動建立命名模式為 的服務受管安全群組`CloudFront-VPCOrigins-Service-SG`。此安全群組完全由 管理 AWS，不應編輯。

若要允許來自 CloudFront 的流量到達 VPC 原始伺服器，請更新連接至原始資源 (ALB、NLB 或 EC2 執行個體） 的安全群組，以使用下列其中一種方法允許傳入流量：
+ **選項 1：**允許來自 CloudFront 受管字首清單的流量。如需詳細資訊，請參閱[使用 CloudFront 受管字首清單](LocationsOfEdgeServers.md#managed-prefix-list)。這也可以在建立 VPC 原始伺服器之前完成。
+ **選項 2：**允許來自 CloudFront 服務受管安全群組 () 的流量`CloudFront-VPCOrigins-Service-SG`。這只能在建立 VPC 原始伺服器並建立服務受管安全群組之後完成。此組態會進一步限制，因為它只會將流量限制在您的 CloudFront 分佈。

**重要**  
請勿建立名稱開頭為 的自有安全群組`CloudFront-VPCOrigins-Service-SG`。這是服務受管安全群組的 AWS 預留命名模式。如需詳細資訊，請參閱[建立安全群組](https://docs.aws.amazon.com/vpc/latest/userguide/creating-security-groups.html)。

### 通訊協定和功能限制
<a name="protocol-feature-restrictions"></a>

VPC 原始伺服器不支援下列項目：
+ WebSockets
+ gRPC 流量
+ 使用 Lambda@Edge 的原始伺服器請求和原始伺服器回應觸發條件

## 建立 VPC 原始伺服器 (新分佈)
<a name="new-vpc-origin"></a>

下列程序說明如何在 CloudFront 主控台中為新的 CloudFront 分佈建立 VPC 原始伺服器。或者，您可以使用 [CreateVpcOrigin](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateVpcOrigin.html) 和 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html) API 操作搭配 AWS CLI 或 AWS SDK。

**為新的 CloudFront 分佈建立 VPC 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇 **VPC 原始伺服器**、**建立 VPC 原始伺服器**。

1. 填妥必要的欄位。針對**原始伺服器 ARN**，選取 Application Load Balancer、Network Load Balancer 或 EC2 執行個體的 ARN。如果您沒有看到 ARN，您可以複製特定資源 ARN 並將其貼到這裡。

1. 選擇**建立 VPC 原始伺服器**。

1. 等待您的 VPC 原始伺服器狀態變更為**已部署**。此程序最多需要 15 分鐘的時間。

1. 選擇**分佈**、**建立分佈**。

1. 對於**原始伺服器網域**，請從下拉式清單中選取您的 VPC 原始伺服器資源。

   如果您的 VPC 原始伺服器是 EC2 執行個體，請將執行個體的**私有 IP DNS 名稱**複製並貼到**原始伺服器網域**欄位中。

1. 完成建立分佈。如需詳細資訊，請參閱[在主控台中建立 CloudFront 分佈](distribution-web-creating-console.md#create-console-distribution)。

## 建立 VPC 原始伺服器 (現有分佈)
<a name="existing-vpc-origin"></a>

下列程序說明如何在 CloudFront 主控台中為現有的 CloudFront 分佈建立 VPC 原始伺服器，這有助於確保應用程式的持續可用性。或者，您可以使用 [CreateVpcOrigin](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateVpcOrigin.html) 和 [UpdateDistributionWithStagingConfig](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistributionWithStagingConfig.html) API 操作搭配 AWS CLI 或 AWS SDK。

或者，您可以選擇將 VPC 原始伺服器新增至現有的分佈，而無需建立臨時分佈。

**為現有的 CloudFront 分佈建立 VPC 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇 **VPC 原始伺服器**、**建立 VPC 原始伺服器**。

1. 填妥必要的欄位。針對**原始伺服器 ARN**，選取 Application Load Balancer、Network Load Balancer 或 EC2 執行個體的 ARN。如果您沒有看到 ARN，您可以複製特定資源 ARN 並將其貼到這裡。

1. 選擇**建立 VPC 原始伺服器**。

1. 等待您的 VPC 原始伺服器狀態變更為**已部署**。此程序最多需要 15 分鐘的時間。

1. 在導覽窗格中，選擇 **Distributions (分佈)**。

1. 選擇您分佈的 ID。

1. 在**一般**索引標籤的**持續部署**下，選擇**建立臨時分佈**。如需詳細資訊，請參閱[使用 CloudFront 持續部署，安全地測試 CDN 組態變更](continuous-deployment.md)。

1. 依照**建立臨時分佈**精靈中的步驟來建立臨時分佈。包括下列步驟：
   + 對於**原始伺服器**，選擇**建立原始伺服器**。
   + 對於**原始伺服器網域**，請從下拉式功能表中選取您的 VPC 原始伺服器資源。

     如果您的 VPC 原始伺服器是 EC2 執行個體，請將執行個體的**私有 IP DNS 名稱**複製並貼到**原始伺服器網域**欄位中。
   + 選擇 **Create Origin (建立原始伺服器)**。

1. 在您的臨時分佈中，測試 VPC 原始伺服器。

1. 將臨時分佈組態提升為主要分佈。如需詳細資訊，請參閱[提升臨時分佈組態](working-with-staging-distribution-continuous-deployment-policy.md#promote-staging-distribution-configuration)。

1. 將子網路設為私有，以移除對 VPC 原始伺服器的公開存取。執行此操作後，將無法透過網際網路探索 VPC 原始伺服器，但 CloudFront 仍然可以進行私有存取。如需詳細資訊，請參閱《*Amazon VPC 使用者指南*》中的[將子網路與路由表建立關聯或取消關聯](https://docs.aws.amazon.com/vpc/latest/userguide/WorkWithRouteTables.html#AssociateSubnet)。

## 更新 VPC 原始伺服器
<a name="update-vpc-origin"></a>

下列程序說明如何在 CloudFront 主控台中更新 CloudFront 分佈的 VPC 原始伺服器。或者，您可以使用 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html) 和 [UpdateVpcOrigin](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateVpcOrigin.html) API 操作搭配 AWS CLI 或 AWS SDK。

**更新 CloudFront 分佈的現有 VPC 原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 在導覽窗格中，選擇 **Distributions (分佈)**。

1. 選擇您分佈的 ID。

1. 選擇 **Behaviors (動作)** 索引標籤。

1. 請確定 VPC 原始伺服器不是快取行為的預設原始伺服器。

1. 選擇 **Origins (原始伺服器)** 索引標籤。

1. 選取您要更新的 VPC 原始伺服器，然後選擇**刪除**。這會取消 VPC 原始伺服器與分佈的關聯。重複步驟 2 至 7，以取消 VPC 原始伺服器與任何其他分佈的關聯。

1. 選擇 **VPC 原始伺服器**。

1. 選取 VPC 原始伺服器，然後選擇**編輯**。

1. 進行更新，然後選擇**更新 VPC 原始伺服器**。

1. 等待您的 VPC 原始伺服器狀態變更為**已部署**。此程序最多需要 15 分鐘的時間。

1. 在導覽窗格中，選擇 **Distributions (分佈)**。

1. 選擇您分佈的 ID。

1. 選擇 **Origins (原始伺服器)** 索引標籤。

1. 選擇 **Create Origin (建立原始伺服器)**。

1. 對於**原始伺服器網域**，請從下拉式功能表中選取您的 VPC 原始伺服器資源。

   如果您的 VPC 原始伺服器是 EC2 執行個體，請將執行個體的**私有 IP DNS 名稱**複製並貼到**原始伺服器網域**欄位中。

1. 選擇 **Create Origin (建立原始伺服器)**。這會再次將 VPC 原始伺服器與您的分佈建立關聯。重複步驟 12 至 17，將更新的 VPC 原始伺服器與任何其他分佈建立關聯。

## AWS 區域 支援 VPC 原始伺服器
<a name="vpc-origins-supported-regions"></a>

下列商業商品目前支援 VPC 原始伺服器 AWS 區域。會記下可用區域 (AZ) 例外狀況。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/private-content-vpc-origins.html)

# 限制對 Amazon S3 多區域存取點原始伺服器的存取
<a name="private-content-restricting-access-to-s3-mrap"></a>

您可以使用原始存取控制 (OAC) 來限制對 Amazon S3 多區域存取點原始伺服器的存取。S3 多區域存取點提供全域端點，可根據網路延遲將請求路由至最近的 S3 儲存貯體。

如需搭配標準 Amazon S3 儲存貯體原始伺服器使用 OAC 的詳細資訊，請參閱 [限制對 Amazon S3 原始伺服器的存取](private-content-restricting-access-to-s3.md)。

## 先決條件
<a name="oac-prerequisites-s3-mrap"></a>

在建立和設定 OAC 之前，您必須擁有具有 Amazon S3 多區域存取點原始伺服器的 CloudFront 分佈。原始網域名稱必須使用 S3 多區域存取點主機名稱格式：

`multi-region-access-point-alias.accesspoint.s3-global.amazonaws.com`

如需建立 S3 多區域存取點的詳細資訊，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[建立多區域存取點](https://docs.aws.amazon.com/AmazonS3/latest/userguide/CreatingMultiRegionAccessPoints.html)。

## 授予 CloudFront 存取 S3 多區域存取點的許可
<a name="oac-permission-to-access-s3-mrap"></a>

更新多區域存取點政策，以允許 CloudFront 服務主體 (`cloudfront.amazonaws.com`) 存取多區域存取點。僅在請求代表包含原始伺服器的 CloudFront 分佈時，才使用政策中的`Condition`元素來允許 CloudFront 存取多區域存取點。

如需新增或修改多區域存取點政策的相關資訊，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[多區域存取點政策範例](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPointPermissions.html)。

**Example CloudFront OAC 的多區域存取點政策**  

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowCloudFrontOACAccess",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3::111122223333:accesspoint/Multi-Region-Access-Point-Alias.mrap/object/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront distribution ID"
                }
            }
        }
    ]
}
```

## 授予 CloudFront 存取基礎 S3 儲存貯體的許可
<a name="oac-permission-to-access-s3-mrap-buckets"></a>

除了多區域存取點政策之外，您還必須授予 CloudFront 許可，以存取與多區域存取點相關聯的每個基礎 S3 儲存貯體。您可以使用兩種方式的其中一種來執行此動作：

### 選項 1：僅授予對 CloudFront 的存取權
<a name="oac-s3-mrap-bucket-option1"></a>

將儲存貯體政策新增至每個 S3 儲存貯體，以允許 CloudFront 服務主體存取儲存貯體。當您也需要允許從其他來源直接存取儲存貯體時，請使用此選項。

**Example 基礎儲存貯體的 S3 儲存貯體政策**  

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowCloudFrontOACAccessViaMRAP",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-us-east-1/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront distribution ID"
                }
            }
        }
    ]
}
```

### 選項 2：將完整儲存貯體存取權委派給多區域存取點
<a name="oac-s3-mrap-bucket-option2"></a>

授予多區域存取點對每個基礎儲存貯體的完整存取權。透過此方法，所有對儲存貯體的存取都由多區域存取點政策控制，可簡化存取管理。對於不需要直接存取儲存貯體的使用案例，我們建議使用此選項。

**Example 委派存取多區域存取點的 S3 儲存貯體政策**  

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DelegateAccessToMRAP",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::amzn-s3-demo-bucket-us-east-1",
                "arn:aws:s3:::amzn-s3-demo-bucket-us-east-1/*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:DataAccessPointArn": "arn:aws:s3::111122223333:accesspoint/Multi-Region-Access-Point-Alias.mrap"
                }
            }
        }
    ]
}
```

如需詳細資訊，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[多區域存取點政策範例](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPointPermissions.html#MultiRegionAccessPointPolicyExamples)。

**重要**  
您必須將此儲存貯體政策新增至與多區域存取點相關聯的每個 S3 儲存貯體。如果有任何儲存貯體缺少政策，則路由至該儲存貯體的 CloudFront 請求將被拒絕。

### SSE-KMS
<a name="oac-s3-mrap-sse-kms"></a>

如果基礎 S3 儲存貯體中的物件使用伺服器端加密搭配 AWS KMS (SSE-KMS) 加密，您必須確保 CloudFront 分佈具有使用 AWS KMS 金鑰的許可。由於 S3 多區域存取點可以將請求路由到多個區域中的儲存貯體，因此您必須將陳述式新增至基礎儲存貯體使用 SSE-KMS 的每個區域中的 KMS 金鑰政策。如需如何修改金鑰政策的相關資訊，請參閱《*AWS Key Management Service 開發人員指南*》中的[變更金鑰政策](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-modifying.html)。

**Example KMS 金鑰政策陳述式**  
下列範例顯示 KMS 金鑰政策陳述式，允許具有 OAC 的 CloudFront 分佈存取 SSE-KMS 的 KMS 金鑰。  

```
{
    "Sid": "AllowCloudFrontServicePrincipalSSE-KMS",
    "Effect": "Allow",
    "Principal": {
        "Service": "cloudfront.amazonaws.com"
    },
    "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey*"
    ],
    "Resource": "*",
    "Condition": {
        "StringEquals": {
            "aws:SourceArn": "arn:aws:cloudfront::111122223333:distribution/CloudFront distribution ID"
        }
    }
}
```

**重要**  
您必須將此金鑰政策陳述式新增至基礎 S3 儲存貯體使用 SSE-KMS 加密的每個區域中的 KMS 金鑰。

## 建立原始存取控制
<a name="create-oac-s3-mrap"></a>

若要建立原始存取控制 (OAC)，您可以使用 AWS 管理主控台 CloudFormation、 AWS CLI、 或 CloudFront API。

------
#### [ Console ]

**如要建立原始存取控制**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 於左側導覽窗格中，選擇 **Origin access** (原始存取)。

1. 選擇 **Create control setting** (建立控制設定)。

1. 在 **Create control setting** (建立控制設定) 表單上，執行下列動作：

   1. 於 **Details** (詳細資訊) 窗格中，輸入 **Name** (名稱) 和 (選用) **Description** (描述)，以用於原始存取控制。

   1. 於 **Settings** (設定) 窗格中，建議您保留預設設定 (**Sign requests (recommended)**) (簽署請求 (建議使用))。如需詳細資訊，請參閱[原始存取控制的進階設定](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3)。

1. 從**原始伺服器類型**下拉式清單中選擇 **S3 多區域存取點**。

1. 選擇**建立**。

   建立 OAC 之後，請記下 **Name** (名稱)。您需要於下列程序中進行使用。

**將原始存取控制新增至分佈中的 S3 多區域存取點原始伺服器**

1. 在 [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) 中開啟 CloudFront 主控台。

1. 選擇具有您要新增 OAC 之 S3 多區域存取點原始伺服器的分佈，然後選擇**原始**伺服器索引標籤。

1. 選取您要新增 OAC 的 S3 多區域存取點原始伺服器，然後選擇**編輯**。

1. 針對**原始存取**，選擇**原始存取控制設定 (建議使用)**。

1. 在 **Origin access control** (原始存取控制) 下拉式功能表中，選擇您想要使用的 OAC。

1. 選擇**儲存變更**。

分佈開始部署至所有 CloudFront 邊緣節點。當節點收到新組態時，它會簽署其傳送至 S3 多區域存取點原始伺服器的所有請求。

------
#### [ CLI ]

使用 **create-origin-access-control** 命令：

```
aws cloudfront create-origin-access-control \
    --origin-access-control-config '{
        "Name": "my-s3-mrap-oac",
        "Description": "OAC for S3 Multi-Region Access Point",
        "SigningProtocol": "sigv4a",
        "SigningBehavior": "always",
        "OriginAccessControlOriginType": "s3mrap"
    }'
```

------
#### [ CloudFormation ]

在 中指定下列值`OriginAccessControlConfig`：
+ `SigningProtocol`: `sigv4a`
+ `SigningBehavior`：`never`、 `always`或 `no-override`
+ `OriginAccessControlOriginType`: `s3mrap`

**Example CloudFormation 範本**  

```
Type: AWS::CloudFront::OriginAccessControl
Properties:
  OriginAccessControlConfig:
    Description: An optional description for the origin access control
    Name: my-s3-mrap-oac
    OriginAccessControlOriginType: s3mrap
    SigningBehavior: always
    SigningProtocol: sigv4a
```

------

## 簽署行為
<a name="oac-signing-behavior-s3-mrap"></a>

S3 多區域存取點原始伺服器的簽署行為選項與一般 Amazon S3 儲存貯體原始伺服器的簽署行為選項相同。如需詳細資訊，請參閱 [原始存取控制的進階設定](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3) 中的*限制對 Amazon S3 原始伺服器的存取*。

# 限制對 Application Load Balancers 的存取
<a name="restrict-access-to-load-balancer"></a>

您可以將內部和面向網際網路的 Application Load Balancer 與 Amazon CloudFront 搭配使用。您可以使用 VPC 來源，將私有子網路之中的內部 Application Load Balancer 與 CloudFront 搭配使用。CloudFront VPC 來源可讓您從私有 VPC 子網路中託管的應用程式提供內容，而無需將其暴露至公共網際網路。如需詳細資訊，請參閱[使用 VPC 原始伺服器限制存取](private-content-vpc-origins.md)。

如果您使用面向網際網路的 Application Load Balancer 搭配 CloudFront，您可以使用下列安全性緩解措施來防止使用者直接存取 Application Load Balancer，並僅允許透過 CloudFront 存取。

1. 設定 CloudFront 將自訂 HTTP 標頭新增至其傳送至 Application Load Balancer 的要求。

1. 將 Application Load Balancer 設定為僅轉寄包含自訂 HTTP 標頭的請求。

1. 需要 HTTPS 來改善此解決方案的安全性。

CloudFront 還可以幫助減少延遲，甚至吸收一些分散式阻斷服務 (DDoS) 攻擊。

如果您的使用案例需要直接透過網際網路從 CloudFront 和 Application Load Balancer 雙重存取 Web 應用程式，請考慮分割您的 Web 應用程式 API (如下所示)：
+ API 必須通過 CloudFront。在此情況下，請考慮使用個別的私有 Application Load Balancer 做為來源。
+ 需要透過 Application Load Balancer 存取的 API。在此情況下，您會略過 CloudFront。

對於在 Elastic Load Balancing 中由面向網際網路的 Application Load Balancer 提供的 Web 應用程式或其他內容，CloudFront 可以快取物件並直接提供給使用者 (檢視器)，以減少 Application Load Balancer 的負載。面對網際網路的負載平衡器具有可公開解析的 DNS 名稱，並會透過網際網路將用戶端的請求路由至目標。

如需詳細資訊，請參閱下列主題。完成這些步驟後，使用者只能透過 CloudFront 存取您的 Application Load Balancer。

**Topics**
+ [設定 CloudFront 將自訂 HTTP 標頭新增至請求](#restrict-alb-add-custom-header)
+ [將 Application Load Balancer 設定為僅轉寄包含特定標頭的請求](#restrict-alb-route-based-on-header)
+ [(選用) 改善此解決方案的安全性](#restrict-alb-improve-security)
+ [（選用） 使用 CloudFront AWS的受管字首清單限制對原始伺服器的存取](#limit-access-to-origin-using-aws-managed-prefixes)

## 設定 CloudFront 將自訂 HTTP 標頭新增至請求
<a name="restrict-alb-add-custom-header"></a>

您可以將 CloudFront 設定為將自訂 HTTP 標頭新增至其傳送至來源的請求 (在本例中為 Application Load Balancer)。

**重要**  
此用例依賴於保留自訂標頭名稱和值密碼。如果標頭名稱和值不是密碼，其他 HTTP 用戶端可能會將它們包含在直接傳送至 Application Load Balancer 的請求中。這可能會導致 Application Load Balancer 的運作方式如同來自 CloudFront 的請求一樣，即便當它們並非來自於此。若要防止這種情況，請保留自訂標頭名稱和值密碼。

您可以使用 CloudFront 主控台 CloudFormation或 CloudFront API，設定 CloudFront 將自訂 HTTP 標頭新增至原始伺服器請求。

**新增自訂 HTTP 標頭 (CloudFront 主控台)**  
在 CloudFront 主控台中，使用**原始伺服器設定中的原始伺服器自訂標頭****設定**。輸入**標頭名稱**及其**值**。  
在生產中，使用隨機產生的標頭名稱和值。將標頭名稱和值視為安全憑證，如使用者名稱和密碼。
當您建立或編輯現有 CloudFront 發佈的來源，以及建立新發佈時，您可以編輯**來源自訂標頭**設定。如需詳細資訊，請參閱[更新分佈](HowToUpdateDistribution.md)及[建立分發](distribution-web-creating-console.md)。

**新增自訂 HTTP 標頭 (CloudFormation)**  
在 CloudFormation 範本中，使用 `OriginCustomHeaders` 屬性，如下列範例所示。  
此範例中的標頭名稱和值僅為演示。在生產中，使用隨機產生的值。將標頭名稱和值視為安全登入資料，如使用者名稱和密碼。

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  TestDistribution:
    Type: 'AWS::CloudFront::Distribution'
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: app-load-balancer.example.com
            Id: Example-ALB
            CustomOriginConfig:
              OriginProtocolPolicy: https-only
              OriginSSLProtocols:
                - TLSv1.2
            OriginCustomHeaders:
               - HeaderName: X-Custom-Header
                 HeaderValue: random-value-1234567890
        Enabled: 'true'
        DefaultCacheBehavior:
          TargetOriginId: Example-ALB
          ViewerProtocolPolicy: allow-all
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
        PriceClass: PriceClass_All
        ViewerCertificate:
          CloudFrontDefaultCertificate: 'true'
```
如需詳細資訊，請參閱《*AWS CloudFormation 使用者指南*》中的 [Origin](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-origin.html) 和 [OriginCustomHeader](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-origincustomheader.html) 屬性。

**新增自訂 HTTP 標頭 (CloudFront API)**  
在 CloudFront API 中，使用 `Origin` 中的 `CustomHeaders` 物件。如需詳細資訊，請參閱《*Amazon CloudFront API 參考*》中的 [CreateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateDistribution.html) 和 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)，以及 SDK 或其他 API 用戶端的文件。

有一些標頭名稱不能指定為來源自訂標頭。如需詳細資訊，請參閱[CloudFront 無法新增到原始伺服器請求的自訂標頭](add-origin-custom-headers.md#add-origin-custom-headers-denylist)。

## 將 Application Load Balancer 設定為僅轉寄包含特定標頭的請求
<a name="restrict-alb-route-based-on-header"></a>

將 CloudFront 設定為將自訂 HTTP 標頭新增至其傳送至 Application Load Balancer 的請求之後 (請參閱[上一章節](#restrict-alb-add-custom-header))，您可以將負載平衡器設定為僅轉寄包含此自訂標頭的請求。您可以透過在負載平衡器的接聽程式中新增規則並修改預設規則來執行此動作。

**先決條件**  
若要使用下列程序，您必須具有至少一個接聽程式的 Application Load Balancer。如果您尚未建立，請參閱《[Application Load Balancer 使用者指南](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html)*》中的建立 Application Load Balancer*。

下列程序會修改 HTTPS 接聽程式。您可以使用相同的程序來修改 HTTP 接聽程式。

**更新 Application Load Balancer 接聽程式中的規則**

1. 新增新規則。使用[新增規則](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html#add-rule)中的指示，並進行下列修改：
   + 將規則新增至 CloudFront 分佈來源的負載平衡器。
   + 針對**新增條件**選擇 **Http 標頭**。指定您在 CloudFront 中新增為來源自訂標頭的 HTTP 標頭名稱和值。
   + 針對**新增動作**選擇**轉送至**。選擇要轉寄請求的目標群組。

1. 編輯負載平衡器接聽程式中的預設規則。使用[編輯規則](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html#edit-rule)中的指示，並進行下列修改：
   + 編輯 CloudFront 分佈來源的負載平衡器預設規則。
   + 刪除預設動作，然後針對**新增動作**選擇**傳回固定回應**。
   + 在**回應代碼**中，輸入 **403**。
   + 在**回應主體**中，輸入 **Access denied**。

完成這些步驟後，負載平衡器接聽程式會有兩個規則。一個規則會轉寄包含 HTTP 標頭的請求 (來自 CloudFront 的請求)。另一個規則會傳送固定回應給所有其他請求 (不是來自 CloudFront 的請求)。

您可以將請求傳送至您的 CloudFront 發佈，並傳送一個請求至您的 Application Load Balancer，以驗證解決方案是否正常運作。對 CloudFront 的請求會傳回您的 Web 應用程式或內容，而直接傳送給 Application Load Balancer 的請求會傳回純文字訊息 `Access denied` 的 `403` 回應。

## (選用) 改善此解決方案的安全性
<a name="restrict-alb-improve-security"></a>

為了改善此解決方案的安全性，您可以將 CloudFront 發佈設定為在向 Application Load Balancer 傳送請求時始終使用 HTTPS。請記住，此解決方案僅適用於保留自訂標頭名稱和值密碼的情況下。使用 HTTPS 有助於防止竊聽者發現標頭名稱和值。我們也建議定期輪換標頭名稱和值。

**針對來源請求使用 HTTPS**  
若要將 CloudFront 設定為針對來源請求使用 HTTPS，請將**來源協定政策**設定設定為**僅限 HTTPS**。此設定可在 CloudFront 主控台 CloudFormation和 CloudFront API 中使用。如需詳細資訊，請參閱[通訊協定 (僅限自訂原始伺服器)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginProtocolPolicy)。

您將 CloudFront 設定為使用 HTTPS 處理原始請求時，也適用下列條件：
+ 您必須設定 CloudFront，以使用原始伺服器請求政策將 `Host` 標頭轉送至原始伺服器。您可以使用 [AllViewer 受管原始伺服器請求政策](using-managed-origin-request-policies.md#managed-origin-request-policy-all-viewer)。
+ 請確定您的 Application Load Balancer 具有 HTTPS 接聽程式 (如[上節](#restrict-alb-route-based-on-header)所示)。如需詳細資訊，請參閱《*Application Load Balancer 使用者指南*》中的[建立 HTTPS 接聽程式](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)。如欲使用 HTTPS 接聽程式，需要您擁有與路由至 Application Load Balancer 網域名稱相符的 SSL/TLS 憑證。
+ CloudFront 的 SSL/TLS 憑證只能在 `us-east-1` AWS 區域 in(ACM) 中請求 AWS Certificate Manager （或匯入）。由於 CloudFront 是全域服務，因此會自動將憑證從 `us-east-1` 區域分佈到與您的 CloudFront 分佈相關聯的所有區域。
  + 例如，如果您在 `ap-southeast-2` 區域中有 Application Load Balancer (ALB)，則必須在 `ap-southeast-2` 區域 (適用於在 CloudFront 和 ALB 原始伺服器之間使用 HTTPS) 和 `us-east-1` 區域 (適用於在檢視器和 CloudFront 之間使用 HTTPS) 中設定 SSL/TLS 憑證。這兩個憑證都應該符合路由至 Application Load Balancer 的網域名稱。如需詳細資訊，請參閱[AWS 區域 適用於 的 AWS Certificate Manager](cnames-and-https-requirements.md#https-requirements-aws-region)。
+ 如果 Web 應用程式的最終使用者 (也稱為*檢視器*或*用戶端*) 可以使用 HTTPS，您也可以將 CloudFront 設定為偏好 (甚至需要) 來自最終使用者的 HTTPS 連線。若要這樣做，請使用**檢視器協定政策**設定。您可以將它設定為將最終使用者從 HTTP 重新導向至 HTTPS，或拒絕使用 HTTP 的請求。此設定可在 CloudFront 主控台 CloudFormation和 CloudFront API 中使用。如需詳細資訊，請參閱[檢視器通訊協定政策](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)。

**輪換標頭名稱和值**  
除了使用 HTTPS 之外，我們還建議定期輪換標頭名稱和值。執行這項操作的高階步驟如下：

1. 設定 CloudFront 將其他自訂 HTTP 標頭新增至其傳送至 Application Load Balancer 的請求。

1. 更新 Application Load Balancer 接聽程式規則，以轉寄包含此其他自訂 HTTP 標頭的請求。

1. 設定 CloudFront 停止將來源自訂 HTTP 標頭新增至其傳送至 Application Load Balancer 的請求。

1. 更新 Application Load Balancer 接聽程式規則，以停止轉寄包含來源自訂 HTTP 標頭的請求。

如需完成這些步驟的詳細資訊，請參閱前一章節。

## （選用） 使用 CloudFront AWS的受管字首清單限制對原始伺服器的存取
<a name="limit-access-to-origin-using-aws-managed-prefixes"></a>

若要進一步限制對 Application Load Balancer 的存取，您可以設定與 Application Load Balancer 相關聯的安全群組，以便在服務使用 受管字首清單時只接受來自 CloudFront AWS的流量。這可防止不是來自 CloudFront 的流量在網路層 (第 3 層) 或傳輸層 (第 4 層) 到達 Application Load Balancer。

如需詳細資訊，請參閱[使用 AWS Amazon CloudFront 部落格文章的受管字首清單限制對原始伺服器的存取](https://aws.amazon.com//blogs/networking-and-content-delivery/limit-access-to-your-origins-using-the-aws-managed-prefix-list-for-amazon-cloudfront/)。

# 限制您內容的地理分佈
<a name="georestrictions"></a>

您可以使用*地理限制*功能 (有時也稱為*地理封鎖*)，來防止特定地理位置的使用者存取您透過 Amazon CloudFront 分佈所散發的內容。若要使用地理限制，您有兩個選擇：
+ 使用 CloudFront 地理位置限制功能。使用此選項可限制對與分佈相關聯的所有檔案的存取，並限制在國家/地區層級的存取。
+ 使用第三方地理位置服務。使用此選項來針對與分佈相關聯檔案的子集作限制存取，或在比國家/地區層級更細的層級作限制存取。

**Topics**
+ [使用 CloudFront 地理限制](#georestrictions-cloudfront)
+ [使用第三方地理位置服務。](#georestrictions-geolocation-service)

## 使用 CloudFront 地理限制
<a name="georestrictions-cloudfront"></a>

當使用者請求內容時，無論使用者身在何處，CloudFront 通常會為請求的內容提供服務。如果您需要防止特定國家/區域的使用者存取您的內容，則可以使用 CloudFront 地理限制功能執行以下其中一項內容：
+ 只有當使用者位於您允許清單上其中一個核准國家/地區時，才能存取您的內容。
+ 如果使用者位於您封鎖清單上的被禁國家/地區，則阻止其存取您的內容。

例如，若請求來自您未授權分配內容的國家/區域，則可以使用 CloudFront 地理限制來封鎖該請求。

**注意**  
CloudFront 會使用第三方資料庫來判斷使用者的位置。IP 位址與國家/地區之間的映射的準確性因區域而異。根據最近的測試，整總體準確性為 99.8%。如果 CloudFront 無法判斷使用者的位置，CloudFront 會提供使用者所請求的內容。

以下是地理限制的運作方式：

1. 假設您有權僅在列支敦斯登分配您的內容。您更新 CloudFront 分佈，來新增僅包含列支敦斯登的允許清單。(或者，您可以新增包含除了列支敦斯登以外的每個國家/地區的封鎖清單。)

1. 摩納哥的使用者請求您的內容，而 DNS 會將請求路由到位於義大利米蘭的 CloudFront 節點。

1. 米蘭的邊緣節點會查詢您的分佈，並確定摩納哥的使用者沒有下載您的內容的許可。

1. CloudFront 會將 HTTP 狀態碼 `403 (Forbidden)` 傳回使用者。

您可以選擇性地設定 CloudFront，向使用者傳回自訂錯誤訊息，而且也可指定您希望 CloudFront 針對請求檔案的錯誤回應，為其建立快取的留存時間。預設值為 10 秒。如需詳細資訊，請參閱[針對特定的 HTTP 狀態碼建立自訂錯誤頁面](creating-custom-error-pages.md)。

地理限制適用於整個分佈。如果您需要對部分內容套用一個限制，並對內容的其他部分套用不同的限制 (或不限制)，則必須建立單獨 CloudFront 分佈或[使用第三方地理位置服務](#georestrictions-geolocation-service)。

如果您啟用 CloudFront [標準日誌](AccessLogs.md) (即存取日誌)，則可以透過搜尋 `sc-status` 值 (即 HTTP 狀態代碼) 為 `403` 的日誌項目，來識別 CloudFront 已拒絕的請求。不過，如果只使用標準日誌，您無法區分 CloudFront 是根據使用者所在位置而拒絕的請求，還是 CloudFront 因為使用者不具有存取檔案的許可 (有其他的理由) 而拒絕的請求。如果您有第三方地理位置服務，例如 Digital Element 或 MaxMind，則可以根據存取日誌中 `c-ip` (用戶端 IP) 列中的 IP 位址來識別請求的位置。如需有關 CloudFront 標準日誌的詳細資訊，請參閱 [存取日誌 （標準日誌）](AccessLogs.md)。

下列程序說明如何使用 CloudFront 主控台將地理限制新增到現有的分佈。如需有關如何使用主控台建立分佈的詳細資訊，請參閱[建立分發](distribution-web-creating-console.md)。<a name="restrictions-geo-procedure"></a>

**將地理限制功能新增至您的 CloudFront Web 分佈 (主控台)**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇**分佈**，然後選擇您要更新的分佈。

1. 選擇**安全性**分頁，然後選擇**地理限制**。

1. 選擇**編輯**。

1. 選擇 **Allow list (允許清單)** 建立允許的國家/地區清單，或 **Block list (封鎖清單)** 建立封鎖的國家/地區清單。

1. 將所需的國家/地區新增至清單中，然後選擇 **Save changes (儲存變更)**。

## 使用第三方地理位置服務。
<a name="georestrictions-geolocation-service"></a>

CloudFront 地理限制功能可讓您控制內容在國家/地區層級的分佈，以便您在特定的 Web 分佈中散發所有檔案。如果您有適用地理限制的使用案例，但此限制並非遵循國界，或是想透過指定分佈，來限制僅可存取提供的某些檔案，您可將 CloudFront 與第三方地理位置服務組合使用。這讓您不僅可以根據國家/地區控制對內容的存取，還可以根據城市、郵遞區號，甚至是緯度和經度來控制對內容的存取。

當您使用第三方地理位置服務時，我們建議您使用 CloudFront 的已簽署 URL，這可讓您指定到期日期和時間，在此日期和時間之後 URL 不再有效。此外，我們建議您使用 Amazon S3 儲存貯體做為原始伺服器，因為您可使用 CloudFront [原始存取控制](private-content-restricting-access-to-s3.md)，以防止使用者直接從原始伺服器存取您的內容。如需有關已簽署的 URL 和原始存取控制的詳細資訊，請參閱 [使用已簽署 URL 和已簽署 Cookie 提供私有內容](PrivateContent.md)。

以下步驟解釋如何使用第三方地理位置服務來控制對檔案的存取。

**使用第三方地理位置服務來限制對 CloudFront 分佈中檔案的存取**

1. 使用地理位置服務取得帳戶。

1. 將內容上傳至 Amazon S3 儲存貯體。

1. 設定 Amazon CloudFront 和 Amazon S3 以提供私有內容。如需詳細資訊，請參閱 [使用已簽署 URL 和已簽署 Cookie 提供私有內容](PrivateContent.md)。

1. 寫入您的 Web 應用程式，以執行下列動作：
   + 將每個使用者請求的 IP 位址傳送到地理位置服務。
   + 評估來自地理位置服務傳回的值，以判斷使用者是否位於您希望 CloudFront 分配內容的位置。
   + 如果您想要將內容分配至使用者的位置，請為您的 CloudFront 內容產生已簽署的 URL。如果您不想將內容分配到該位置，請將 HTTP 狀態碼 `403 (Forbidden)` 傳回給使用者。或者，您可以設定 CloudFront 以返回自訂錯誤訊息。如需詳細資訊，請參閱[針對特定的 HTTP 狀態碼建立自訂錯誤頁面](creating-custom-error-pages.md)。

   如需詳細資訊，請參閱您所使用的地理位置服務的文件。

您可以使用 Web 伺服器變動變數來獲得瀏覽您的網站的使用者的 IP 位址。請注意以下警告：
+ 如果您的 Web 伺服器透過負載平衡器無法連線至網際網路，則可以使用 Web 伺服器變數來獲得遠端 IP 位址。不過，此 IP 位址不一定是使用者的 IP 位址。它也可以是代理伺服器的 IP 位址，取決於使用者如何連接到網際網路。
+ 如果您的 Web 伺服器透過負載平衡器連線至網際網路，則 Web 伺服器變數可能包含負載平衡器的 IP 位址，而非使用者的 IP 位址。在這個組態中，我們建議您使用 `X-Forwarded-For` HTTP 標頭中的最後一個 IP 位址。此標頭通常包含多個 IP 位址，其中大部分用於代理或負載平衡器。清單中的最後一個 IP 位址最有可能與使用者的地理位置相關聯。

如果您的 Web 伺服器無法連接到負載平衡器，我們建議您使用 Web 伺服器變數而非 `X-Forwarded-For` 標頭，以避免 IP 位址詐騙。

# 使用欄位層級加密來協助保護敏感資料
<a name="field-level-encryption"></a>

透過 Amazon CloudFront，您可以使用 HTTPS 強制執行原始伺服器的安全端對端連線。欄位層級加密可新增額外的安全層，可讓您在整個系統處理過程中保護特定的資料，以便只有特定應用程式才能看到它。

欄位層級加密可讓您的使用者安全地將敏感資訊上傳到您的 Web 伺服器。使用者提供的敏感資訊會在邊緣、靠近使用者處加密，並在整個應用程式堆疊中保持加密。此加密可確保只有需要資料的應用程式 (並具有可解密的登入資料) 才能執行這項操作。

若要使用欄位層級加密，則可以設定 CloudFront 分佈以指定要加密的 POST 請求中的一組欄位，以及對其加密的公有金鑰。您可以在請求中加密多達 10 個資料欄位。(您無法使用欄位層級加密對請求中的所有資料進行加密；您必須指定要加密的各個欄位。)

當將帶有欄位層級加密的 HTTPS 請求轉發到原始伺服器，並且該請求被路由到原始應用程式或子系統中時，敏感資料仍然被加密，從而降低了敏感資料遭受洩露或意外遺失資料的風險。出於業務考量而需對敏感資料存取的元件，例如需要存取信用卡號碼的付款系統，可以使用適當的私有金鑰來解密和存取該資料。

**注意**  
為了使用欄位層級加密，您的原始伺服器必須支援區塊編碼。

![\[CloudFront 中的現場層級加密\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/images/fleoverview.png)


CloudFront 欄位層級加密使用非對稱加密，也稱為公有金鑰加密。您提供了 CloudFront 的公有金鑰，所指定的所有敏感資料都會進行自動加密。您提供給 CloudFront 的金鑰不能用於解密加密的值；只有您的私有金鑰可以做到這一點。

![\[只將敏感資料加密\]](http://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/images/encryptedfields.png)


**Topics**
+ [欄位層級加密概觀](#field-level-encryption-overview)
+ [設定欄位層級加密](#field-level-encryption-setting-up)
+ [在您的原始伺服器解密資料欄位](#field-level-encryption-decrypt)

## 欄位層級加密概觀
<a name="field-level-encryption-overview"></a>

以下步驟概述了設定欄位層級加密。對於特定的步驟，請參閱[設定欄位層級加密](#field-level-encryption-setting-up)。

1. **取得公有金鑰/私有金鑰對。**CloudFront 開始在 CloudFront 中設定欄位層級加密前，必須取得並新增公有金鑰。

1. **建立欄位層級加密的設定檔。**CloudFront 您在 CloudFront 中建立的欄位層級加密設定檔定義了要加密的欄位。

1. **建立欄位層級加密的組態。**組態會指定要使用的設定檔 (根據請求的內容類型或查詢引數)，用來將特定資料欄位加密。您也可以針對不同案例選擇所需的請求轉發行為選項。例如，您可以設定要求 URL 中查詢引數所指定的設定檔名稱不存在於 CloudFront 的行為。

1. **至快取行為的連結。**將組態連結到分佈的快取行為，以指定 CloudFront 應該何時加密資料。

## 設定欄位層級加密
<a name="field-level-encryption-setting-up"></a>

依照以下步驟開始使用欄位層級加密。若要了解欄位層級加密的配額 (先前稱為限制)，請參閱 [配額](cloudfront-limits.md)。
+ [步驟 1：建立 RSA 金鑰對](#field-level-encryption-setting-up-step1)
+ [步驟 2：將您的公有金鑰新增到 CloudFront](#field-level-encryption-setting-up-step2)
+ [步驟 3：建立欄位層級加密的設定檔。](#field-level-encryption-setting-up-step3)
+ [步驟 4：建立組態](#field-level-encryption-setting-up-step4)
+ [步驟 5：將組態新增到快取行為](#field-level-encryption-setting-up-step5)

### 步驟 1：建立 RSA 金鑰對
<a name="field-level-encryption-setting-up-step1"></a>

若要開始使用，您必須建立包含公有金鑰和私有金鑰的 RSA 金鑰對。公有金鑰可讓 CloudFront 加密資料，私有金鑰使您原始伺服器的元件能夠解密已加密的欄位。您可以使用 OpenSSL 或其他工具來建立金鑰對。金鑰大小必須為 2048 個位元。

例如，如果您使用的是 OpenSSL，您可以使用以下命令來產生長度為 2048 個位元組的金鑰對，並將其儲存在檔案 `private_key.pem` 中：

```
openssl genrsa -out private_key.pem 2048
```

產生的檔案同時包含公有和私有金鑰。要從該檔案中擷取公有金鑰，請執行以下命令：

```
openssl rsa -pubout -in private_key.pem -out public_key.pem
```

公有金鑰檔案 (`public_key.pem`) 包含您在下列步驟中貼上的編碼鍵值。

### 步驟 2：將您的公有金鑰新增到 CloudFront
<a name="field-level-encryption-setting-up-step2"></a>

取得您的 RSA 金鑰對之後，將公有金鑰新增到 CloudFront。<a name="field-level-encryption-setting-up-step2-procedure"></a>

**將您的公有金鑰新增至 CloudFront (主控台)**

1. 登入 AWS 管理主控台 ，並在 開啟 CloudFront 主控台[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)。

1. 在導覽窗格中，選擇 **Public key** (公有金鑰)。

1. 選擇 **Add public key** (新增公有金鑰)。

1. 在 **Key name** (金鑰名稱) 中，輸入金鑰的獨特名稱。名稱不能有空格，並且只能包含英數字元、底線 (\$1) 和 連字號 (-)。最大字元數為 128。

1. 針對 **Key value** (鍵值)，貼上公有金鑰的編碼鍵值 (包括 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 行)。

1. 針對 **Comment (註解)**，加入選擇性的註解。例如，您可以包含公有金鑰的到期日期。

1. 選擇 **Add** (新增)。

透過重複程序中的步驟，您可以新增更多用於 CloudFront 的金鑰。

### 步驟 3：建立欄位層級加密的設定檔。
<a name="field-level-encryption-setting-up-step3"></a>

將至少一個公有金鑰新增到 CloudFront 後，建立設定檔，告知 CloudFront 要加密哪些欄位。<a name="field-level-encryption-setting-up-step3-procedure"></a>

**建立欄位層級加密的設定檔 (主控台)**

1. 在導覽窗格中，選擇 **Field-level encryption (欄位層級加密)**。

1. 選擇 **Create profile (建立設定檔)**。

1. 填寫下列欄位：  
**設定檔名稱**  
請輸入設定檔的專屬名稱。名稱不能有空格，並且只能包含英數字元、底線 (\$1) 和 連字號 (-)。最大字元數為 128。  
**公有金鑰名稱**  
在下拉式清單中，選擇您在步驟 2 中新增到 CloudFront 公有金鑰的名稱。CloudFront 使用金鑰來加密您在此設定檔中指定欄位。  
**供應商名稱**  
輸入片語以協助識別您的金鑰，例如您取得到金鑰對的供應商。當應用程式解密資料欄位時，將需要此資訊以及私有金鑰。供應商名稱不能有空格，並且只能包含英數字元、冒號 (:)、底線 (\$1) 和 連字號 (-)。最大字元數為 128。  
**欄位名稱模式符合**  
輸入您希望 CloudFront 加密的資料欄位的名稱，或識別請求中資料欄位名稱的模式。選擇 \$1 選項來新增您想要使用此金鑰加密的所有欄位。  
對於欄位名稱模式，您可以輸入資料欄位的整個名稱，例如 DateOfBirth，或僅使用萬用字元 (\$1) 的名稱的第一部分，例如 CreditCard\$1。除了可選的萬用字元 (\$1) 外，欄位名稱模式必須只包含英數字元、方括號 ([和])、句號 (.)、底線 (\$1) 和連字號 (-)。  
請確定不要為不同的欄位名稱模式使用重疊的字元。例如，如果您有 ABC\$1 的欄位名稱模式，則不能新增另一個 AB\$1 的欄位名稱模式。此外，欄位名稱區分大小寫，可以使用的字元數上限為 128。  
**註解**  
(選用) 輸入有關此設定檔的評論。最多可使用 128 個字元。

1. 填寫完欄位後，選擇 **Create profile (建立設定檔)**。

1. 如果您想新增更多設定檔，請選擇 **Add profile (新增設定檔)**。

### 步驟 4：建立組態
<a name="field-level-encryption-setting-up-step4"></a>

在您建立一或多個欄位層級加密設定檔後，請建立一個組態，指定包含要加密的資料的請求的內容類型、用於加密的設定檔，以及指定 CloudFront 如何處理加密的其他選項。

例如，當 CloudFront 無法加密資料時，可以指定在以下情況下，CloudFront 是否應該封鎖或轉送請求到您的原始伺服器：
+ **當請求的內容類型不在組態中** – 如果您尚未在組態中新增內容類型，則可以指定 CloudFront 是否應將具有該內容類型的請求轉傳到原始伺服器，而不加密資料欄位，或封鎖請求並傳回一個錯誤。
**注意**  
如果將內容類型新增到組態中，但未指定與該類型一起使用的設定檔，則具有該內容類型的 CloudFront 將一律把請求轉傳到原始伺服器。
+ **當查詢引數中提供的設定檔名稱未知時** – 當您使用分佈中不存在的設定檔名稱指定 `fle-profile` 查詢引數時，您可以指定 CloudFront 是否應將請求發送到原始伺服器，而不加密資料欄位，或封鎖請求並傳回錯誤。

在組態中，還可以指定一個在 URL 中做為查詢參數所提供的設定檔是否要覆寫了一個已對應到該查詢內容類型的設定檔。在預設情況下，如果指定了一個已對應到內容類型的設定檔，則 CloudFront 將使用該設定檔。這可讓您擁有一個預設情況下使用的設定檔，但也會決定您所希望強制執行不同設定檔的特定請求。

因此，例如，您可以指定 (在您的組態中) **SampleProfile** 做為要使用的查詢參引數設定檔。然後，您可以使用 URL `https://d1234.cloudfront.net?fle-profile=SampleProfile` 而非 `https://d1234.cloudfront.net`，來讓 CloudFront 針對此請求使用 **SampleProfile**，而非使用您為請求的內容類型所建立的設定檔。

您最多可以為單一帳戶建立 10 個組態，然後將其中一個組態與的該帳戶的任何分佈的快取行為相關聯。<a name="field-level-encryption-setting-up-step4-procedure"></a>

**建立欄位層級加密的組態 (主控台)**

1. 在 **Field-level encryption (欄位層級加密)** 頁面，選擇 **Create configuration (建立組態)**。

   注意：如果您尚未建立至少一個設定檔，則不會看到用於建立組態的選項。

1. 請填寫以下欄位指定要使用的設定檔。(有些欄位無法變更。)  
**內容類型 (無法變更)**  
內容類型設定為 `application/x-www-form-urlencoded`，無法變更。  
**預設設定檔 ID (選用)**  
在下拉式清單中選擇設定檔，此設定檔會對應到 **Content type (內容類型)** 欄位中的內容類型。  
**內容格式 (無法變更)**  
內容格式設定為 `URLencoded`，無法變更。

1. 如果您想要變更以下選項的 CloudFront 預設行為，請選取合適的核取方塊。  
**當請求的內容類型未作設定時，請轉發請求到原始來源**  
*如果您尚未指定用於請求內容類型的設定檔*，而要允許請求轉傳到您的原始伺服器，請勾選此核取方塊。  
**使用提供的查詢參數覆寫內容類型的設定檔**  
如果您要允許查詢引數中所提供的設定檔，*覆寫您針對內容類型指定的設定檔*，請勾選此核取方塊。

1. 如果您選取核取方塊，以允許查詢參數來覆寫預設的設定檔，則必須完成組態的下列其他欄位。在這些查詢參數對應中，您最多可以建立五個，以便與查詢一起使用。  
**查詢參數**  
輸入要包含在 URL 中以用於 `fle-profile` 查詢參數的值。這個值通知 CloudFront 使用與此查詢參數相關聯的設定檔 ID (在下一個欄位中指定的)，以用於此查詢的欄位層級加密。  
最多可使用 128 個字元。該值不能包含空格，而且必須使用英數字元或以下字元：破折號 (-)、句點 (.)、底線 (\$1)、星號 (\$1)、加號 (\$1)、百分比 (%)。  
**設定檔 ID**  
在下拉式清單中選擇設定檔，您要將此設定檔與您針對 **Query argument (查詢引數)** 輸入的值建立關聯。  
**當查詢參數中指定的設定檔不存在時，將請求轉發到原始來源**  
*如果在 CloudFront 中未定義查詢參數中指定的設定檔*，且如果您想要允許請求轉到原始伺服器，請選取核取方塊。

### 步驟 5：將組態新增到快取行為
<a name="field-level-encryption-setting-up-step5"></a>

若要使用欄位層級加密，請透過將組態 ID 新增為分佈的值，將組態連結到分佈的快取行為。

**重要**  
若要將欄位層級的加密設定連結至快取行為，必須將分佈設定為永遠使用 HTTPS，並接受來自瀏覽者的 HTTP `POST` 和 `PUT` 請求。也就是說，下列條件必須為真：  
快取行為的 **Viewer Protocol 政策 (檢視器通訊協定政策)** 必須設定為將 **Redirect HTTP to HTTPS (HTTP 重新引導至 HTTPS)** 或 **HTTPS Only (僅 HTTPS)**。（在 CloudFormation 或 CloudFront API 中， `ViewerProtocolPolicy` 必須設定為 `redirect-to-https`或 `https-only`。)
快取行為的**允許的 HTTP 方法**必須設為 **GET、HEAD、OPTIONS、PUT、POST、PATCH、DELETE**。（在 CloudFormation 或 CloudFront API 中， `AllowedMethods` 必須設定為 `GET`、`HEAD`、`OPTIONS`、`PUT`、`POST`、`PATCH`、`DELETE`。 這些可以依任何順序指定。)
原始伺服器設定的 **Origin Protocol 政策 (原始伺服器通訊協定政策)** 必須設定為 **Match Viewer (符合檢視器)** 或 **HTTPS Only (僅 HTTPS)**。（在 CloudFormation 或 CloudFront API 中， `OriginProtocolPolicy` 必須設定為 `match-viewer`或 `https-only`。)

如需詳細資訊，請參閱[所有分佈設定參考](distribution-web-values-specify.md)。

## 在您的原始伺服器解密資料欄位
<a name="field-level-encryption-decrypt"></a>

CloudFront 透過使用 [AWS Encryption SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html) 加密資料欄位。資料在整個應用程式堆疊中保持加密狀態，只能由具有解密憑證的應用程式存取。

加密後，加密文字是 base64 編碼的。當您的應用程式在原始伺服器解密文字時，必須先對加密文字解碼，然後使用 AWS 加密開發套件來解密資料。

以下程式碼範例說明應用程式如何在原始伺服器中解密資料。注意下列事項：
+ 為了簡化範例，本範例從工作目錄中的檔案載入公有金鑰和私有金鑰 (以 DER 格式)。在實務上，您可以將私有金鑰存放在安全的離線位置，例如離線硬體安全模組中，並將公有金鑰分佈到您的開發團隊。
+ CloudFront 在加密資料時使用特定的資訊，並且應該在原始伺服器上使用相同的一組參數對其進行解密。在初始化 MasterKey 時使用的參數 CloudFront 包括下列項目：
  + PROVIDER\$1NAME：當您建立欄位層級加密設定檔時指定了這個值。在這裡使用相同的值。
  + KEY\$1NAME：當您將公有金鑰上傳至 CloudFront 時，您為其建立一個名稱，然後在設定檔中指定了金鑰名稱。在這裡使用相同的值。
  + ALGORITHM：CloudFront 使用 `RSA/ECB/OAEPWithSHA-256AndMGF1Padding` 做為加密演算法，因此您必須使用相同的演算法來解密資料。
+ 如果您以加密文字做為輸入來執行以下範例程式時，則解密的資料將輸出到您的主控台。如需詳細資訊，請參閱 AWS 加密 SDK 中的 [Java 範例程式碼](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/java-example-code.html)。

### 範本程式碼
<a name="field-level-encryption-decrypt-sample"></a>

```
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.jce.JceMasterKey;

/**
 * Sample example of decrypting data that has been encrypted by CloudFront field-level encryption.
 */
public class DecryptExample {

    private static final String PRIVATE_KEY_FILENAME = "private_key.der";
    private static final String PUBLIC_KEY_FILENAME = "public_key.der";
    private static PublicKey publicKey;
    private static PrivateKey privateKey;

    // CloudFront uses the following values to encrypt data, and your origin must use same values to decrypt it.
    // In your own code, for PROVIDER_NAME, use the provider name that you specified when you created your field-level
    // encryption profile. This sample uses 'DEMO' for the value.
    private static final String PROVIDER_NAME = "DEMO";
    // In your own code, use the key name that you specified when you added your public key to CloudFront. This sample
    // uses 'DEMOKEY' for the key name.
    private static final String KEY_NAME = "DEMOKEY";
    // CloudFront uses this algorithm when encrypting data.
    private static final String ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";

    public static void main(final String[] args) throws Exception {

        final String dataToDecrypt = args[0];

        // This sample uses files to get public and private keys.
        // In practice, you should distribute the public key and save the private key in secure storage.
        populateKeyPair();

        System.out.println(decrypt(debase64(dataToDecrypt)));
    }

    private static String decrypt(final byte[] bytesToDecrypt) throws Exception {
        // You can decrypt the stream only by using the private key.

        // 1. Instantiate the SDK
        final AwsCrypto crypto = new AwsCrypto();

        // 2. Instantiate a JCE master key
        final JceMasterKey masterKey = JceMasterKey.getInstance(
                publicKey,
                privateKey,
                PROVIDER_NAME,
                KEY_NAME,
                ALGORITHM);

        // 3. Decrypt the data
        final CryptoResult <byte[], ? > result = crypto.decryptData(masterKey, bytesToDecrypt);
        return new String(result.getResult());
    }

    // Function to decode base64 cipher text.
    private static byte[] debase64(final String value) {
        return Base64.decodeBase64(value.getBytes());
    }

    private static void populateKeyPair() throws Exception {
        final byte[] PublicKeyBytes = Files.readAllBytes(Paths.get(PUBLIC_KEY_FILENAME));
        final byte[] privateKeyBytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILENAME));
        publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(PublicKeyBytes));
        privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
    }
}
```