通過SecurityUtils獲取Subject詳解


獲取Subject

使用shiro獲取Subject的方法:

            Subject subject = SecurityUtils.getSubject();

為什么,不管在哪通過SecurityUtils獲取的Subject 都是同一個呢?
而且Subject 里面還有用戶的信息.

猜想

首先,能在各個地方獲取Subject 只有一種辦法,就是通過ThreadLocal類來實現,那么SecurityUtils肯定維護了一個ThreadLocal.

源碼分析

首先看getSubject方法:
在這里插入圖片描述
點到ThreadContext類:
在這里插入圖片描述
說明是ThreadContext類維護了一個ThreadLocal;

ThreadContext是什么時候跟Subject綁定的呢?

我們發現有個方法:bind(Subject subject),
看誰掉了這個方法:
在這里插入圖片描述
在這里插入圖片描述
是SubjectCallable里面就開始綁定了,我們只要看是誰新建了SubjectCallable這個類就好了,發現在Subject里面執行execute的時候新建的,同時將subject也就是this傳進去了.
在這里插入圖片描述
現在明了了,上篇講到subject創建詳解
里面有一張圖:
在這里插入圖片描述
在創建了subject的時候就通過execute來執行過濾器鏈的方法,這時候將創建好的subject跟ThreadContext進行了綁定,所以我們在任何地方都可以通過SecurityUtils.getSubject()來獲取Subject.

猜想ThreadLocal是跟當前線程綁定的,如果我springmvc里面使用異步方法執行,在異步處理過程中能獲取到subject嗎?

是可以的,我們看ThreadContext里的的ThreadLocal具體實現就知道了:
在這里插入圖片描述
主要功勞就是InheritableThreadLocal實現,這個實現大概做的事情就是如果父線程里面使用ThreadLocal了,然后在父線程里面又創建子線程,這是會將父線程的ThreadLocal拷貝到子線程里面,所以在異步線程里面是可以獲取到subject的.
這時候就會想如果是異步線程池呢,這一塊比較復雜,因為
InheritableThreadLocal實現的時候,如果是異步線程池,在一開始設置了ThreadLocal,他是有緩存的,詳情見:解決父子線程ThreadLocal中的緩存問題

驗證:

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM