您好,登錄后才能下訂單哦!
這篇“SpringSecurity之SecurityContextHolder怎么使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“SpringSecurity之SecurityContextHolder怎么使用”文章吧。
我認為SecurityContextHolder只是為SecurityContext提供一種存儲策略,只是主導了他的存儲方式及地址。
使用中我們表面上看起來SecurityContext的存儲都是通過SecurityContextHolder在控制人們就習以為常的說成了Security Context存儲在了SecurityContextHolder中,至于真相我們看源碼慢慢分析。
public class SecurityContextHolder { // ~ Static fields/initializers // ===================================================================================== public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL"; public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL"; public static final String MODE_GLOBAL = "MODE_GLOBAL"; public static final String SYSTEM_PROPERTY = "spring.security.strategy"; private static String strategyName = System.getProperty(SYSTEM_PROPERTY); private static SecurityContextHolderStrategy strategy; private static int initializeCount = 0;
首先從源碼可以看到SecurityContextHolder提供了一個SecurityContextHolderStrategy存儲策略進行上下文的存儲,進入到Security ContextHolderStrategy接口,由下圖我們可以清晰的看到其總共有三個實現類。
分別對應三種存儲策略,這里我不知道為什么99的文章都只說了threadlocal和global兩種。
要不是看了下實現類我都信了。
就跟字面意思一樣三種策略分別對應threadlocal,global,InheritableThreadLocal三種方式。
繼續回到源碼我們詳細看這三種方式。
private static void initialize() { if (!StringUtils.hasText(strategyName)) { // 如果沒有設置自定義的策略,就采用MODE_THREADLOCAL模式 strategyName = MODE_THREADLOCAL; } // ThreadLocal策略 if (strategyName.equals(MODE_THREADLOCAL)) { strategy = new ThreadLocalSecurityContextHolderStrategy(); } // 采用InheritableThreadLocal,它是ThreadLocal的一個子類 else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) { strategy = new InheritableThreadLocalSecurityContextHolderStrategy(); } // 全局策略,實現方式就是static SecurityContext contextHolder else if (strategyName.equals(MODE_GLOBAL)) { strategy = new GlobalSecurityContextHolderStrategy(); } else { // Try to load a custom strategy 自定義的策略,通過返回創建出 try { Class<?> clazz = Class.forName(strategyName); Constructor<?> customStrategy = clazz.getConstructor(); strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } initializeCount++; }
由源碼我們可以得出SecurityContextHolder 默認使用的是THREADLOCAL模式,光從名字看感覺就是存儲在threadlocal中的策略到底是不是我們去源碼中分別一探究竟:
final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { // ~ Static fields/initializers // ===================================================================================== private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<>(); 。。。。。。 }
final class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { // ~ Static fields/initializers // ===================================================================================== private static final ThreadLocal<SecurityContext> contextHolder = new InheritableThreadLocal<>(); 。。。。。。 }
final class GlobalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { // ~ Static fields/initializers // ===================================================================================== private static SecurityContext contextHolder; 。。。。。。 }
到這里那些說SecurityContext存儲在SecurityContextHolder的大佬們我認為應該是不嚴謹的。
默認是將SecurityContext存儲在threadlocal中,可能是spring考慮到目前大多數為BS應用,一個應用同時可能有多個使用者,每個使用者又對應不同的安全上下,Security Context Holder為了保存這些安全上下文。
缺省情況下,使用了ThreadLocal機制來保存每個使用者的安全上下文。
因為缺省情況下根據Servlet規范,一個Servlet request的處理不管經歷了多少個Filter,自始至終都由同一個線程來完成。這樣就很好的保證了其安全性。
但是當我們開發的是一個CS本地應用的時候,這種模式就不太適用了。
spring早早的就考慮到了這種情況,這個時候我們就可以設置為Global模式僅使用一個變量來存儲SecurityContext。比如還有其他的一些應用會有自己的線程創建,并且希望這些新建線程也能使用創建者的安全上下文。
這種效果,我們就可以通過將SecurityContextHolder配置成MODE_INHERITABLETHREADLOCAL策略達到。
以上就是關于“SpringSecurity之SecurityContextHolder怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。