Skip to main content

本頁目的

在限時分享連結中,若想直接使用核發時決定的條件,除了驗證 URL 簽章之外,還需要統一從哪裡取得值。 本頁以一個範例說明:在 URL 中包含報表類型與輸出格式,並回傳預覽用的 JSON。 本頁適用於 Laravel 13。URL 產生的整體說明請參閱 URL 生成,取得輸入的基礎請參閱 HTTP Request。
簽章並不保護整個請求。表單與 JSON 的 body 不在簽章範圍內。 已簽章的 query 值,請在簽章驗證後以 $request->query('format') 這類方式取得。 使用 input()、all() 或動態屬性時,可能會取得未簽章的 body 值。GET 請求同樣需要做此區分。

簽章保護的範圍

input() 不僅處理 query string,也會處理 body。Laravel 在合併這些輸入時,body 的值優先於 query string 的值。 相對地,query() 只會取得 query string 的值。 簽章驗證成功,與之後讀取的值是否已簽章,是兩件需要分別確認的事。

實作限時預覽連結

1. 定義進行驗證的路由

在 routes/web.php 中定義必須帶有簽章的具名路由。 這裡不操作資料庫或檔案,只回傳收到的條件。
  • signed middleware 會在 closure 執行前驗證簽章與有效期限。若無效則回傳 403。
  • 使用 query() 明確地從 query string 取得處理所需的值。
  • 驗證是針對取得的陣列進行。簽章驗證並不保證值的型別或業務上允許的範圍。
本範例傳給 Validator::make() 的只有以 query() 取出的值。 若在用來驗證已簽章 query 值的地方改用 $request->all(),就會處理到包含 body 在內的輸入。

2. 在可信任的核發流程中產生 URL

註冊具名路由後,在核發連結的處理中使用以下程式碼。 report 與 format 不是路徑的佔位符,因此會被加入 query string。
此 URL 除了指定的條件外,還包含 expires 與 signature。 expires 與 signature 是 Laravel 使用的保留參數,請勿將其作為業務用的參數名稱。 在實際應用程式中公開核發流程時,請勿讓任何人都能以任意條件核發連結,並進行必要的認證與授權。

3. 確認正常使用

在有效期限內直接開啟核發的 URL,會回傳以下 JSON。
連結過期時,路由上的 signed middleware 會回傳 403。 簽章 URL 並非一次性 token。在本範例中,有效期限內可重複使用同一個 URL。 若只允許使用一次,需要在簽章之外另行管理已使用狀態。

區分排除於驗證之外的值

若想允許前端加上的頁碼等參數,可以透過 hasValidSignatureWhileIgnoring(['page']) 將其排除於簽章驗證之外。 不過,被排除的值任何人都能修改,因此請勿將其視為已簽章的條件。 例如,顯示用的 page 與核發時固定的 report、format 作用不同。 請勿僅為了方便,就排除用來判斷目標資料、收件者、費用等的值。
上面的實作範例使用一般的 signed middleware,因此 page 也沒有被排除。 若需要加上 query 參數,請先決定產生端與驗證端各自要將哪些內容納入簽章。

使用相對簽章時

在簽章中不包含網域的設計下,需搭配產生時的 absolute: false 與驗證時的 signed:relative。
此時,請將前面路由的 middleware('signed') 改為 middleware('signed:relative')。 即使使用相對簽章,body 也不會被簽章,因此以 query() 取得值的原則不變。

實作檢查清單

  • 接收路由強制要求簽章驗證。
  • 以 query() 取得已簽章的 query 值。
  • 另外驗證值的格式與允許範圍。
  • 未將排除於簽章驗證之外的值當作核發時固定的條件使用。
  • 產生端與驗證端的絕對簽章、相對簽章設定一致。
  • 未將知道 URL 視同已登入使用者的權限。

相關頁面與一手資料

最後修改於 2026年10月16日