SecurityContext 和 SecurityContextHolder 是 Spring Security 的兩個基本類。
- SecurityContext 用於儲存當前已驗證使用者的詳細資訊,也稱為principle。因此,如果要獲取使用者名稱或任何其他使用者詳細資訊,首先需要獲取 SecurityContext。
- SecurityContextHolder 是一個輔助類,用於訪問安全上下文。預設情況下,它使用 ThreadLocal 物件來儲存安全上下文,這意味著即使不傳遞 SecurityContext 物件,同一執行執行緒中的方法也始終可以使用安全上下文。不過不用擔心網路應用程式中的 ThreadLocal 記憶體洩漏,Spring Security 會負責清理 ThreadLocal。
順便說一下,這並不是 SecurityContextHolder 儲存當前 SecurityContext 的唯一方法,它還可以在啟動時配置策略,以指定儲存上下文的方式。例如,你可以在獨立應用程式中使用 SecurityContextHolder.MODE_GLOBAL 策略。
需要學習的關鍵是如何從 SecurityContextHolder 獲取 SecurityContext,然後從中檢索當前使用者的詳細資訊?例如,如果想知道當前登入使用者的使用者名稱,如何在 Spring Security 中獲取?
要獲取當前使用者名稱,首先需要一個從 SecurityContextHolder 獲取的 SecurityContext。SecurityContext 將使用者詳細資訊儲存在一個 Authentication 物件中,可以透過呼叫 getAuthentication() 方法獲取該物件。
獲得 Authentication 物件後,可以將其轉換為 UserDetails 物件,也可以原樣使用。UserDetails 物件是 Spring Security 用來儲存使用者相關資訊的物件。
如何在 Spring Security 中獲取當前登入使用者名稱
以下是在 Spring Security 中獲取安全上下文並獲得當前登入使用者名稱的程式碼:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); |
getContext() 返回的物件是 SecurityContext 介面的一個例項。該物件儲存線上程本地儲存區中。
在 Spring Security 中,getPrincipal() 方法通常會返回 UserDetails 物件,其中包含當前登入使用者的所有詳細資訊。
總之,如果你仔細觀察,就會發現當我們考慮 Spring 和依賴注入時,這並不是一段好程式碼。因此,如果你需要知道當前登入使用者的詳細資訊,例如在 Spring MVC 控制器中,我建議你宣告一個依賴關係,讓 Spring 為你提供 Principal 物件,而不是你去查詢它們,從而建立一個緊密耦合的系統。
import java.security.Principal; |
或者,也可以要求提供身份驗證物件,而不是 Principal 物件,如下圖所示:
import org.springframework.security.core.Authentication; |
以上就是關於 Spring Security 中什麼是安全上下文以及如何從 SecurityContextHolder 類中獲取 SecurityContext 的全部內容。這些都是一些基本類,因此你必須熟悉它們。
儲存部分(即 SecurityContext 儲存在 ThreadLocal 中)是可選的,但瞭解細節也很有好處。請記住,如果需要使用者詳細資訊(如使用者名稱等),最好在 Spring MVC 控制器中請求 Principal 或 Authentication 物件,而不是使用 SecurityContextHolder 來獲取。