在Spring Security中對用戶進行認證的是AuthenticationManager,其只有壹個方法,嘗試對封裝了認證信息的Authentication進行身份驗證,如果成功,則返回完全填充的Authentication(包括授予的權限)。
AuthenticationManager 只關註認證成功與否而並不關心具體的認證方式。例如我們可以通過用戶名及密碼、短信、刷臉、OAuth2協議等方式進行認證。對於這些具體認證方式是交給了AuthenticationProvider來負責。
下面展示了AuthenticationProvider的部分實現
AuthenticationManager與AuthenticationProvider 是怎麽被創建使用,以及如何自由的添加認證方式的問題,在下面的內容中將進壹步分析
前面章節分析了WebSecurityConfiguration配置類裏面相關的內容,現在回到@EnableWebSecurity 註解上,我們接著分析下@EnableGlobalAuthentication內部都做了些啥
其重點就是導入了AuthenticationConfiguration配置對象
AuthenticationConfiguration 中還導入了ObjectPostProcessorConfiguration配置,該配置比較簡單,就是實例化了壹個bean,而該Bean在前面的章節中也在不斷的用到
下面,我們深入分析下AuthenticationConfiguration配置類的實現。
先簡單的說下AuthenticationManager構建的主體過程
由上門可知,其默認使用DefaultPasswordEncoderAuthenticationManagerBuilder作為認證管理的構建器,下面分析其build()方法的執行過程。
DefaultPasswordEncoderAuthenticationManagerBuilder在執行build()方法時,其父類AbstractConfiguredSecurityBuilder的doBuild()方法被執行,前面有說過,這個方法是個模板方法,如下所示:
接著我們分析下這三個默認的GlobalAuthenticationConfigurerAdapter類型的實例中init和configure方法都做了啥
該類的目的純粹是為了添加InitializeUserDetailsManagerConfigurer配置,通過在其configure方法階段創建DaoAuthenticationProvider對象,最終被添加到ProviderManager中
Springboot的自動化配置中會默認創建InMemoryUserDetailsManager,請參考 Spring Security解析二:自動化裝配
我們也可以通過配置來指定,例如:
接著進壹步研究下DaoAuthenticationProvider都做了些啥,它是怎麽對身份進行認證的?
可見上的操作主要是從某個地方得到用戶信息,然後檢查用戶的狀態,如果檢查失敗則拋出相應的異常,否則返回成功的認證信息。
上面的retrieveUser與additionalAuthenticationChecks是需要繼續研究的地方
上面通過userDetailsService來得到用戶的信息,並通過passwordEncoder來驗證密碼是否正確,而這兩個對象是通過上面 3.2小結裏的InitializeUserDetailsManagerConfigurer中從ApplicationContext獲得。
該類的目的純粹是為了添加InitializeUserDetailsManagerConfigurer配置,通過在其configure方法階段從ApplicationContext中得到AuthenticationProvider類型的Bean,並加入到ProviderManager中
小結:
經過上來的步驟後,在DefaultPasswordEncoderAuthenticationManagerBuilder的authenticationProviders屬性中添加了壹個或多個AuthenticationProvider,接下來的工作便是執行DefaultPasswordEncoderAuthenticationManagerBuilder的performBuild()方法完成AuthenticationManager的創建工作。當然,其實該方法是在父類AuthenticationManagerBuilder中的。
返回的其實是ProviderManager,而ProviderManager可以看成是AuthenticationManager的代理對象,裏面保存了多個AuthenticationManager的實現。
Spring Security默認情況下為我們創建了壹個基於用戶名和密碼進行驗證的AuthenticationManager實例,同時收集ApplicationContext中的AuthenticationProvider類型的Bean 壹起添加到ProviderManager(AuthenticationManager的子類)中供需要的地方進行使用。