SpringSecurity認證流程

2021-08-28 20:59:06 字數 3965 閱讀 2760

在之前的文章《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)

SpringSecurity自定義登入認證

spring security預設的登入表單只有username和password,但實際業務中我們可能需要使用其他的字段校驗,因此需要重寫認證部分。springsecurityfilterchain org.springframework.web.filter.delegatingfilterpr...

springsecurity Run As認證服務

zhangxin.security.service.roleservice.loadmenu role user,run as temp zhangxin.security.runasdemo.runasdate.showdate role admin,role run as temp object...

Token Cookie Session的認識了解

token token的意思是 令牌 是使用者身份的驗證方式,最簡單的token組成 uid 使用者唯一的身份標識 time 當前時間的時間戳 sign 簽名,由token的前幾位 雜湊演算法壓縮成一定長的十六進製制字串,可以防止惡意第三方拼接token請求伺服器 還可以把不變的引數也放進token...