登出請求應使用 GET 還是 POST?

REST,Security
Remote
0
06:48 AM · Dec 01 ,2025

1. 概述

在傳統的 Web 應用程序中,登錄通常需要將用户名和密碼發送到服務器進行身份驗證。雖然這些元素在 GET 請求中的 URL 參數中理論上可行,但將它們封裝到 POST 請求中顯然更好。

但是,退出登錄是否可以通過 GET 請求提供,因為這不需要發送任何敏感信息?

在本教程中,我們將探討這一設計考慮的各個方面。

2. 服務器端會話管理

當管理服務器端會話時,必須暴露一個端點來銷燬這些會話。我們可能會受到 GET 方法的簡單性吸引。當然,這在技術上可以工作,但可能會導致一些不良行為。

某些進程,如 Web 加速器,會為用户預取 GET 鏈接。預取鏈接的目的是立即為用户點擊該鏈接時提供內容,從而縮短頁面加載時間。這些進程假設 GET 鏈接嚴格用於返回內容,而不是更改任何狀態。

如果我們將登出操作作為 GET 請求暴露,並將其呈現為鏈接,這些進程可能會無意中在嘗試預取頁面上的鏈接時將用户登出。

如果我們的登出 URL 不是靜態可用的,例如由 JavaScript 確定,則可能不會有問題。但是,HTTP/1.1 RFC 明確指出,GET 方法應僅用於返回內容,並且用户不能對 GET 請求的副作用負責。我們應在可能的情況下遵循此建議。

相比之下,RFC 將 POST 方法描述為可以提交數據(我們的會話或會話 ID)到數據處理進程(登出)的方法。這更符合我們試圖實現的目標。

2.1. Spring Security

默認情況下,Spring Security 要求登出請求為類型 POST。但是,我們可以讓 Spring 在禁用 CSRF 保護時使用 GET 登出請求:

protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
    ...
}

3. 無狀態 REST

當我們管理無狀態 REST 會話時,“註銷”的概念會發生改變。在無狀態環境中,每個請求都包含完整的會話信息。因此,通過使用 JavaScript 簡單地丟棄會話,而不是發送任何類型的請求,就可以實現“註銷”操作。

然而,出於安全原因,仍然應該通知服務器註銷操作,以便黑名單被撤銷的 JWT。這可以防止在“註銷”後使用會話。

即使在無狀態環境中,註銷時仍然必須向服務器發送請求。 由於這種請求的意圖不是檢索內容,因此不應使用 GET 方法。相反,會話應通過 POST 方法顯式地發送到服務器,以指示註銷。

4. 結論

在本次討論中,我們簡要探討了記錄退出請求應使用 GET 還是 POST 的常見設計問題。

我們考慮了以下幾個方面:

  • 從語義上講,GET 請求不應產生任何狀態相關的副作用
  • 用户可能正在運行的瀏覽器進程可能會包含預取鏈接。如果記錄退出請求使用 GET,預取進程可能會意外地在登錄後將用户註銷
  • 即使是無狀態會話也應向服務器報告註銷事件,這應通過 POST 請求完成
user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.