跳至主要内容

CORS 與允許的來源

可公開金鑰可以配置允許的來源清單,即允許使用該金鑰的網站。本頁介紹在哪些環節檢查此清單、檢查失敗時瀏覽器會顯示什麼,以及此清單無法提供哪些保護。

來源由頁面的通訊協定、主機和連接埠組成,例如 https://www.example.com 或 http://localhost:3000。來源不包含路徑。

此清單為選用配置​

可公開金鑰在清單為空時仍可使用。**清單為空意味著任何來源都可以使用該金鑰。**建立金鑰時不指定來源,就會處於這種狀態;以後也可以清空清單。

將金鑰用於正式網站之前,請先新增允許的來源。配置清單後,即使有人把您的金鑰複製到其他人的網頁中,該網頁也無法使用它。有關此限制的保護範圍及其限制,請參閱下文。

伺服器金鑰不受此清單影響。無論清單包含什麼內容,伺服器金鑰都無法從瀏覽器中使用。

如何填寫項目​

規則範例
只包含通訊協定、主機以及選用的連接埠。不得包含路徑、查詢參數或末尾斜槓。https://www.example.com,而不是 https://www.example.com/
必須使用 https。只有 localhost、127.0.0.1 和 [::1] 可以使用 http。API 金鑰頁面不接受 [::1],請透過金鑰管理 API 設定。http://localhost:3000
必須完全匹配。不支援通配符,子域名屬於不同的來源。包含 * 的項目會按原樣保存,但不會匹配任何網站。https://example.com 和 https://www.example.com 是兩個不同的項目
連接埠屬於來源的一部分。請省略預設連接埠(https 為 443,http 為 80)。https://example.com,而不是 https://example.com:443
每個金鑰最多可配置 100 個項目。重復項目會被拒絕。

項目會以小寫形式保存,並去除預設連接埠,以便與瀏覽器傳送的值一致。

從磁碟直接開啟的頁面(file://)沒有可新增的來源。開發時請透過 http://localhost 提供頁面。

您可以在 kaleidr.com/api-keys 的 API 金鑰頁面配置清單,也可以透過金鑰管理 API 中的 allowed_origins 進行設定。

清單會在哪些環節檢查​

步驟檢查內容失敗時的結果
1. 工作階段交換如果金鑰配置了來源清單,請求的 Origin 標頭必須位於該清單中。傳回 403 origin_not_allowed,不核發工作階段。完全缺少 Origin 標頭時傳回 403 origin_required。
2. 每次執行階段呼叫工作階段權杖只能在核發時綁定的來源使用。傳回 403 session_origin_mismatch。
3. 每次執行階段呼叫工作階段綁定的來源必須仍位於金鑰的來源清單中。傳回 401。從金鑰中移除來源後,該來源已經核發的工作階段也會失效。
4. 攜帶金鑰的底圖請求嵌入式編輯器在向 https://tile.kaleidr.com 請求樣式、精靈圖和字型時會傳送您的可公開金鑰。頁面所在網站必須列於金鑰清單中,金鑰才能被識別。請求將被視為未攜帶金鑰,可能傳回 429 tile_access_restricted。
5. 回應只有憑證有效且來源被允許時,API 才會新增 Access-Control-Allow-Origin。瀏覽器會阻止頁面讀取回應。

第 5 步屬於正常的 CORS 機制,也是瀏覽器中出現此類錯誤表現的原因。

預檢要求​

瀏覽器在傳送帶有 JSON 請求本文的跨站 POST 之前,會先傳送 OPTIONS 預檢要求。Kaleidr 對每個預檢要求都會傳回 204,並回顯請求來源,因為預檢要求不攜帶憑證,無法根據金鑰進行驗證。來源清單是在實際請求階段套用的。

預檢回應標頭值
Access-Control-Allow-MethodsGET, POST, OPTIONS
Access-Control-Allow-HeadersAuthorization, Content-Type, Accept, X-Api-Key, X-Request-Id
Access-Control-Max-Age600

如果請求傳送了任何其他標頭,瀏覽器中的預檢就會失敗。請勿在頁面發出的呼叫中新增自訂標頭。

對於被允許的回應,API 還會傳送 Access-Control-Expose-Headers: Retry-After, X-Request-Id,以便頁面程式碼讀取這兩個標頭。API 不使用 Cookie,因此從不傳送 Access-Control-Allow-Credentials。

來源被拒絕時會看到什麼​

來源或憑證被拒絕時,回應中不會包含 Access-Control-Allow-Origin 標頭。瀏覽器隨後會阻止您的程式碼讀取回應。因此,頁面無法看到 401 或 403 的回應本文,只會收到網路錯誤。

在控制台中:

Access to fetch at 'https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions' from origin
'https://www.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.

隨後還會出現包含 [kaleidr:chat](或您掛載的產品名稱)的 SDK 錯誤。頁面不會渲染任何內容。

要查明真正原因,請開啟瀏覽器的**網路(Network)**選項卡,選擇 sessions 請求,然後查看其狀態和回應:

網路分頁中的狀態及程式碼原因解決方法
403 origin_not_allowed目前頁面的來源不在金鑰清單中。新增請求 Origin 標頭中顯示的完整來源。
401 Invalid or missing API key金鑰輸入錯誤、已撤銷或已過期。在 API 金鑰頁面檢查該金鑰。
403 server_key_in_browser頁面傳送了伺服器金鑰。在頁面中使用可公開金鑰,並輪換伺服器金鑰。
403 session_origin_mismatch工作階段權杖被用於與請求該工作階段時不同的來源。在實際使用工作階段的頁面上重新交換工作階段。
預檢失敗,未出現 POST請求傳送了允許清單之外的標頭。移除自訂標頭。

憑證和來源都透過驗證後,後續錯誤就可以被頁面讀取,也不會產生 CORS 錯誤。如果金鑰對該來源有效,但無權存取所請求的產品,工作階段交換將傳回可讀取的 403(product_not_allowed、insufficient_scope 或 tier_capability_not_allowed),SDK 則會紀錄 kaleidr session exchange failed (403)。有效工作階段收到 429 時,頁面能夠讀取回應本文及 Retry-After 標頭。相關錯誤錯誤代碼詳見身分驗證與權限範圍。

從終端傳送同樣的請求不會出現 CORS 錯誤,因為 CORS 是瀏覽器規則。因此,可以使用 curl 快速檢查金鑰與來源的組合:

curl -i https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions \
-H "X-Api-Key: kld_pk_live_…" \
-H "Origin: https://www.example.com" \
-H "Content-Type: application/json" \
-d '{"product":"chat"}'

允許的來源會傳回 200,並包含 access-control-allow-origin: https://www.example.com。被拒絕的來源則傳回 403 {"detail":"origin_not_allowed"},且不包含該標頭。

為什麼瀏覽器不允許使用伺服器金鑰​

伺服器金鑰是一項長期有效的秘密憑證。任何獲取金鑰的人都可以在其被撤銷之前,以您的組織身份呼叫 API。網頁原始碼是公開的,因此把伺服器金鑰放進頁面就等於洩露金鑰。

Kaleidr 會在三個環節拒絕伺服器金鑰:

  1. SDK 在掛載時拒絕 kld_sk_… 金鑰,在控制台顯示錯誤,並且不會傳送網路請求。
  2. 任何攜帶 Origin 標頭的伺服器金鑰請求都會收到 API 傳回的 403 server_key_in_browser。
  3. 回應不帶 CORS 標頭,因此頁面程式碼無論如何都無法讀取該回應。

這些措施都無法撤銷已經發生的洩露。CORS 阻止的是讀取回應,而不是傳送請求:在 API 拒絕請求之前,金鑰就已傳送出去,查看頁面的人也能夠看到它。如果伺服器金鑰曾出現在網頁中,請輪換該金鑰。

來源清單並不能保護機密​

瀏覽器會如實設定 Origin 標頭,但其他用戶端不受此約束。腳本、命令行工具或伺服器可以任意設定 Origin,如上面的 curl 範例所示。因此:

  • 此清單可以阻止其他網站在其訪客的瀏覽器中使用您的金鑰。這是清單的用途,也確實有效。
  • 此清單無法阻止有意繞過限制的呼叫者複製您的可公開金鑰,並在瀏覽器之外偽裝成您的來源傳送請求。

請據此設計安全策略。凡是可公開金鑰能夠存取的內容,都應視為任何能查看您網頁的人均可獲取:

  • 使用個別金鑰的每月額度上限及請求頻率限制來控制配額風險。參閱配額與速率限制。
  • 除非您願意在該網頁上公開金鑰可存取的資料,否則不要為可公開金鑰賦予 vendor 權限範圍。參閱身分驗證與權限範圍。
  • 每個網站使用獨立金鑰,以便撤銷一個網站的金鑰而不影響其他網站。

有關完整說明,請參閱安全模型。

URL 中的憑證​

平台 API 呼叫始終在標頭中攜帶憑證,而不會放在 URL 中。Kaleidr 嵌入元件的底圖請求是唯一例外:此類請求在 URL 中攜帶瀏覽器憑證,因此可能出現在瀏覽器歷史紀錄和網路紀錄中。對於本來就公開的可公開憑證,這是可以接受的;但伺服器金鑰絕不能這樣使用。請勿將 kld_sk_… 放入任何 URL。

修改清單​

  • 新增來源會在該來源下一次交換工作階段時生效。底圖請求可能需要幾分鐘才能識別變更。
  • 移除來源會拒絕該來源發起的新工作階段交換,並在現有工作階段的下一次請求時使其失效。
  • 清空清單會還原為“允許任何來源”。

相關文檔​