分析整個登入流程,以token去向為線索,層層追蹤,直到跟我們自定義的realm驗證方法結合。
subject subject = securityutils.getsubject();
subject.login(token)(這裡的token收集方式不重要)
可能是從頁面傳遞上來的使用者名稱和密碼或者其他的方式收集的資訊,通過:
usernamepasswordtoken token = new usernamepasswordtoken(username(),password());
獲取token,並呼叫subject.login(token)
這裡的subject.login是delegatingsubject例項的login,所以我們跟蹤到delegatingsubject的login
在該方法中,有原始碼如下
subject subject = this.securitymanager.login(this, token);
securitymanager是乙個介面,我們追蹤login的方法實現其實現類為:defaultsecuritymanager
方法中的原始碼如下
info = this.authenticate(token);
在securitymanager實現類defaultsecuritymanager中將token轉交給自身實現了ahthenticator介面的authenticate方法
在此方法中,只有簡單的一句**
return this.authenticator.authenticate(token);
在上一步的securitymanager方法中呼叫了成員變數authenticator的authenticate方法。
securitymanager是authenticatingsecuritymanager的子類
在該類中實現了securitymanager的authenticate方法,在實現方法中呼叫了:authenticator.authenticate(token)
成員authenticator是modularrealmauthenticator類的例項
這個地方非常關鍵:也就是在這裡,securitymanager把token轉交到realm中進行驗證。
這裡呼叫了modularrealmauthenticator的方法authenticate
但是authenticate方法的實現是在modularrealmauthenticator的父類abstractauthenticator中實現的
所以我們現在把視角轉到abstractauthenticator.authenticate方法中。
在abstractauthenticator.authenticate方法中,我們看到了token被傳遞給了自身的方法doauthenticate
原始碼如下:
info = this.doauthenticate(token);
通過原始碼追蹤,我們知道,只有modularrealmauthenticator類實現了doauthenticate方法
到了這裡,我們就可以看到一些比較熟悉的**了:
protected authenticationinfo doauthenticate
(authenticationtoken authenticationtoken)
throws authenticationexception
return realms.
size()
==1?this
.dosinglerealmauthentication
((realm)realms.
iterator()
.next()
, authenticationtoken)
:this
.domultirealmauthentication
(realms, authenticationtoken)
;
把這行**展開了意思就是:
if
(reams.
size()
==1)else
protected authenticationinfo dosinglerealmauthentication
(realm realm, authenticationtoken token)
else
else
}}
在該方法中,就呼叫了我們自定義實現的方法:
authenticationinfo info = realm.getauthenticationinfo(token);
到了這裡,跟我們當初實現的reaml就形成了乙個閉環。
protected authenticationinfo domultirealmauthentication
(collection
realms, authenticationtoken token)
realms for pam authentication"
, realms.
size()
);} iterator var5 = realms.
iterator()
;while
(var5.
hasnext()
)] using realm [{}]"
, token, realm)
; authenticationinfo info = null;
throwable t = null;
trycatch
(throwable var11)
} aggregate = strategy.
afterattempt
(realm, token, info, aggregate, t);}
else
] does not support token {}. skipping realm."
, realm, token);}
} aggregate = strategy.
afterallattempts
(token, aggregate)
;return aggregate;
}
在多個realm的方法中,需要注意的是authenticationstrategy strategy這個類的例項,
初步推測,這個地方應該跟配置有關係,因為從實現類來看包括了:
abstractauthenticationstrategy抽象類
allsuccessfulstrategy全部成功
atleastonesuccessfulstrategy至少乙個成功
firstsuccessfulstrategy第乙個成功
通過上面的檢視,就是如果只配置乙個realm,就執行第一句
如果否則必然是多個的
因為最開始就已經判斷了是否配置了realm的情況,所以這裡就只有兩種情況。
一種是乙個,另外一種就是多個。
可能在實際的應用過程中,大部分小專案中只有乙個realm。
其實驗證還涉及到其他的一些東西,這裡我只是從登陸的流程來追蹤原始碼,有些說得不清楚,有些可能說得不到位,見諒!!!
Shiro 原始碼分析
shiro 是乙個非常優秀的開源專案,原始碼非常值得學習與研究。我想嘗試做一次 不一樣 的原始碼分析 原始碼分析不再是乙個人的自我享受,而是大家共同 與相互學習。目錄shiro 之 入口 environmentloaderlistener 由 黃勇 分享 shiro 之 filter 上 shiro...
shiro登入流程原始碼詳解(手把手帶你讀原始碼)
一 原始碼解讀 本文使用idea的截圖 1 我們在登入控制層經常會寫這麼一段 usernamepasswordtoken token new usernamepasswordtoken username,password subject subject securityutils.getsubjec...
Vue原始碼分析(流程分析)
使用步驟 1.編寫 頁面 模板 1.直接在html標籤中寫 2.使用template 3.使用單檔案 2.建立vue例項 1.在vue 的建構函式中 data,methods,computer,watcher,props,3.將vue掛載到頁面中 mount 資料驅動模型 vue執行流程 1.獲得模...