在之前的文章《springboot + spring security 基本使用及個性化登入配置》中對springsecurity進行了簡單的使用介紹,基本上都是對於介面的介紹以及功能的實現。 這一篇文章嘗試從原始碼的角度來上對使用者認證流程做乙個簡單的分析。
在具體分析之前,我們可以先看看springsecurity的大概原理:
其實比較簡單,主要是通過一系列的filter對請求進行攔截處理。
我們直接來看usernamepasswordauthenticationfilter
類,
public
class
usernamepasswordauthenticationfilter
extends
abstractauthenticationprocessingfilter
// 登入請求認證
// 生成token,
usernamepasswordauthenticationtoken authrequest = new usernamepasswordauthenticationtoken(username, password);
this.setdetails(request, authrequest);
// 進一步驗證
return
this.getauthenticationmanager().authenticate(authrequest);}}
}
在attemptauthentication
方法中,主要是進行username和password請求值的獲取,然後再生成乙個usernamepasswordauthenticationtoken 物件,進行進一步的驗證。
不過我們可以先看看usernamepasswordauthenticationtoken 的構造方法
public
usernamepasswordauthenticationtoken(object principal, object credentials)
所以接下來我們看
this.getauthenticationmanager().authenticate(authrequest);這裡有乙個authenticationmanager,但是真正呼叫的是
providermanager
。
public
class
providermanager
implements
authenticationmanager, messagesourceaware, initializingbean }}
這裡首先通過provider判斷是否支援當前傳入進來的authentication,目前我們使用的是usernamepasswordauthenticationtoken,因為除了帳號密碼登入的方式,還會有其他的方式,比如socialauthenticationtoken。
根據我們目前所使用的usernamepasswordauthenticationtoken,provider對應的是daoauthenticationprovider
。
public authentication authenticate(authentication authentication) throws authenticationexception
try catch (authenticationexception var7)
// 4.最後的檢查
this.postauthenticationchecks.check(user);
// 5.返回真正的經過認證的authentication
return
this.createsuccessauthentication(principaltoreturn, authentication, user);
}
去呼叫自己實現的userdetailsservice,返回userdetails
對userdetails的資訊進行校驗,主要是帳號是否被凍結,是否過期等
對密碼進行檢查,這裡呼叫了passwordencoder
檢查userdetails是否可用。
返回經過認證的authentication
這裡的兩次對userdetails的檢查,主要就是通過它的四個返回boolean型別的方法。
經過資訊的校驗之後,通過usernamepasswordauthenticationtoken
的構造方法,返回了乙個經過認證的authentication。
拿到經過認證的authentication之後,會再去呼叫successhandler。或者未通過認證,去呼叫failurehandler。
再完成了使用者認證處理流程之後,我們思考一下是如何在多個請求之間共享這個認證結果的呢?
因為沒有做關於這方面的配置,所以可以聯想到預設的方式應該是在session中存入了認證結果。
那麼是什麼時候存放入session中的呢?
我們可以接著認證流程的原始碼往後看,在通過attemptauthentication
方法後,如果認證成功,會呼叫successfulauthentication
,該方法中,不僅呼叫了successhandler,還有一行比較重要的**
securitycontextholder.getcontext().setauthentication(authresult);securitycontextholder是對於threadlocal的封裝。 threadlocal是乙個執行緒內部的資料儲存類,通過它可以在指定的執行緒中儲存資料,資料儲存以後,只有在指定執行緒中可以獲取到儲存的資料,對於其他執行緒來說則無法獲取到資料。 更多的關於threadlocal的原理可以看看我以前的文章。
一般來說同乙個介面的請求和返回,都會是在乙個執行緒中完成的。我們在securitycontextholder中放入了authresult,再其他地方也可以取出來的。
最後就是在securitycontextpersistencefilter
中取出了authresult,並存入了session
securitycontextpersistencefilter也是乙個過濾器,它處於整個security過濾器鏈的最前方,也就是說開始驗證的時候是最先通過該過濾器,驗證完成之後是最後通過。
/**
* 獲取當前登入的使用者
*@return 完整的authentication
*/public object currentuser()
public object currentuser(authentication authentication)
/** *@param userdetails
*@return 只包含了userdetails
*/public object cuurentuser(@authenticationprincipal userdetails userdetails)
spring security 安全框架
本文 http itblood.com spring security security framework.html 安全常識 acegi介紹 以宣告式方式為基於spring的web應用新增認證和授權控制 acegi體系結構 認證管理器 訪問控制管理器。認證 authenticationproce...
SpringSecurity認證流程
在之前的文章 springboot spring security 基本使用及個性化登入配置 中對springsecurity進行了簡單的使用介紹,基本上都是對於介面的介紹以及功能的實現。這一篇文章嘗試從原始碼的角度來上對使用者認證流程做乙個簡單的分析。在具體分析之前,我們可以先看看springse...
SpringSecurity使用技巧
1 鑑權處理頁通常包括四個方面的設定,分別是鑑權失敗 鑑權成功 未鑑權訪問 已鑑權但訪問了受保護許可權。如何自 定義這四類處理。鑑權失敗的預設處理頁面是 spring security login?login error 其預設處理類為 urlauthenticationfailurehandler...