Spring Security修煉手冊(二)————Security的認證流程

    那麼經過第一節的介紹,你們對於Security認證的使用應該具有了一個基本的認識,那麼這節主要有三個知識點。一、初步的帶你們瞭解Security中幾個過濾器(後面會一點點的加入其它過濾器)。二、表單認證的處理流程。三、如何自定義用戶認證邏輯。那麼廢話很少說,直接進入第一點。前端

    哦!對了,我還要補充一點,有不少小夥伴私信我說,怎麼能在用戶完成認證以後,轉跳到上一次請求的頁面,個人回答是:So Easy!別配置defaultSuccessUrl就好了。java

1、Spring Security中的過濾器

    經過第一節的介紹,你們應該知道Security是基於過濾器鏈的,那麼它都有哪些過濾器?而且都是作什麼的呢?下面一張圖,爲你們介紹幾個初級的過濾器。算法

    那麼spring security就是由這樣一個過濾器鏈組成,在spring boot啓動的時候被加載其中,每一個過濾器負責校驗不一樣的信息,最後的FilterSecurityIntercept是在前面的過濾器都校驗經過的時候讀取你對security的配置信息,好比是否爲VIP才能訪問等等,而後會拋出相應的異常,異常會被ExceptionTranslationFilter捕獲,而後將不一樣異常對應的結果返回給前端。spring

    過濾器鏈上綠色的是能夠經過配置來決定它生不生效,藍色和黃色的是必定會執行,且必須按此順序執行,開發人員不可更改的。在補充一下,別看藍色的以Intercept結尾,可是他真的是一個過濾器,不是攔截器。數據庫

   經過名字你們能夠看出來兩個綠色的過濾器一個是用戶名密碼認證過濾器,一個叫基本認證過濾器,那麼當咱們使用表單進行認證的時候,就是在usernamePasswordAuthticationFilter中進行處理的,咱們先簡單看一眼這個類中的代碼:ide

2、表單認證的流程

    下面咱們經過DeBug看一下,在輸入用戶名密碼,點擊登陸後,在後臺代碼中到底發生了什麼。首先咱們在以下四個類中打上斷點: UsernamePasswordAuthenticationFilter、ExceptionTranslationFilter、FilterSecurityIntercept、和咱們的controller。工具

ExceptionTranslationFilter斷點說明:加密

FilterSecurityInterceptor斷點說明:spa

    打好斷點後,咱們執行登陸操做。code

    能夠看到在在UsernamePasswordAuthenticationFilter中獲取到了表單的用戶名密碼信息。而Security中提供了一個接口叫作UserDetailsService,這個接口很是簡單隻有一個方法,傳進來的參數就是當前認證請求的用戶名,返回值叫作UserDetails接口,這個UserDetails實則定義了當前用戶的一些狀態,如基本信息、是否可用、密碼是否過時等等,那麼由於咱們如今尚未去具體的實現,因此都是走的Security默認的實現,後面咱們會有本身的實現,在這裏對比用戶名密碼OK後則經過第一步認證,而後走到FilterSecurityInterceptor,上一小節的圖片中有介紹這個類中有一個對比配置的方法,那麼咱們先走進這個方法內,能夠看到實則對咱們要訪問的URL進行了一次認證。

當咱們有權限訪問此URL時,則會執行咱們的Controller

認證流程結束。

3、自定義認證邏輯

    在第二小節咱們介紹了認證流程中用戶名密碼的對比等是在一個叫UserDetailsService的接口中實現,而  咱們在第一章經過YML配置了一個內存用戶,那麼很明顯,這樣的方式並知足不了咱們的業務需求,咱們通常都是要把用戶名密碼權限這些信息放到數據庫中,下面我來詳細的介紹。

    咱們先看一看UserDetailServer中的代碼:

這個接口中只有一個方法,參數username就是表單中的用戶名,咱們能夠經過用戶名進行CURD的操做,返回值UserDetails一樣也是一個接口,裏面定義了用戶名,密碼,密碼是否過時,帳戶是否可用等一系列的屬性。

接下來咱們具體實現一下:

@Component
public class MyUserDetailsServer implements UserDetailsService {

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		
		return new User(username, "$2a$10$ofPkBDUezOJp6Sik63Q/0.QlU8a1itEyzldjSXqfn2nDPqXjN0Ljm", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
	}

}

這個返回對象User是security給咱們的默認實現,第一個參數就是傳過來的用戶名,第二個參數是經過用戶名進行再數據庫中查詢到的密碼(省略了數據庫操做),第三個參數是從數據庫中查詢出來的當前用戶擁有的權限(省略了數據庫操做,直接使用工具類生成),因爲我使用了加密密碼,因此在SecurityConfig中須要將加密算法注入,代碼以下:

若是想使用其餘加密算法,實現PasswordEncoder接口便可。

這時候咱們重啓項目,用戶名能夠任意,密碼爲,123456a(上面密文對應的原文),這時候個人系統就擁有了自定義認證的功能。

相關文章
相關標籤/搜索