Spring Security極簡入門三部曲(中篇)

白澤來了發表於2021-05-06

Spring Security極簡入門三部曲(中篇)

大家好,我是白澤。通過上篇的學習,我們實現了一個簡單的基於角色驗證的小demo,但是不足之處在於使用者和角色的資訊我們寫死在了記憶體中,而實際專案中必然是寫在資料庫裡的,但是在將資料存入資料庫之前,為了讓你更深入理解Spring Security授權的驗證流程,我需要為你介紹一些關鍵的介面和類(很遺憾這一部分無法完全避免),如果你只想繼續學習Spring Security的使用,直接跳到demo時刻部分吧!

驗證流程

Authentication介面

使用者在前端輸入的登陸資訊傳入後臺後將封裝入一個Authentication介面的實現類,它作為認證和授權的物件穿過整個過濾器鏈,反過來我們也能從Authentication實現類中取出使用者賬戶的相關資訊(使用者名稱、密碼、獲取的許可權等) Authentication實現類的獲取方法:SecurityContextHolder.getContext().getAuthentication()

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();//返回一組已經分發的許可權(角色)

    Object getCredentials();	//返回憑證,即密碼

    Object getDetails();		

    Object getPrincipal();		//返回身份資訊,即使用者名稱

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

過濾器鏈

Spring Security框架核心有一個ProviderManager類,點開它的原始碼,它有一個List providers屬性,這個List集合中就是存放著一個個AuthenticationProvider的實現類(定義了一個個許可權驗證的規則),這個List集合就組成了過濾器鏈

AuthenticationProvider介面:

public interface AuthenticationProvider {
    Authentication authenticate(Authentication var1) throws AuthenticationException;

    boolean supports(Class<?> var1);
}

上面提到,ProviderManager例項的providers屬性存放了AuthenticationProvider介面的實現類集合,而AuthenticationProvider實現類就是實現許可權驗證流程的關鍵,它主要需要實現AuthenticationProvider介面的authenticate()方法,這個方法接收一個Authentication例項,返回一個Authentication例項

結合上面那張ProviderManager的圖,你是不是就理解過濾器鏈是如何工作的了?(一開始就提到了使用者登陸之後,將資料封裝為一個Authentication例項,並由這個例項通過整個過濾器鏈進行驗證,而此時AuthenticationProvider介面的實現類的authenticate()方法不就實現了接收一個Authentication例項,返回一個Authentication例項嗎?一個個AuthenticationProvider實現類組合在一起就得到了鏈式的驗證流程

demo時刻

需要實現的功能:

  1. demo2保留demo1的所有功能,github專案地址

  2. 自定義一個驗證器加入過濾器鏈(實現:當使用者使用baize賬戶登陸時,無論密碼是什麼,都將獲取USER和ADMIN許可權)

程式碼講解

事實上我們只新建了AuthenticationProvider介面的實現類BaiZeAuthenticationProvider,去重寫它的兩個方法,自定義了一個驗證器。並在SecurityConfiguration類中完成注入(相當於自定義過濾器加入過濾器鏈)

@Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //從authentication例項中獲取使用者名稱和密碼(這個authentication例項貫穿流程始終)
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();
        if (username.equals("baize")) {
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));  //ROLE_ADMIN寫法是固定的
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));   //ROLE_USER寫法是固定的
            return new UsernamePasswordAuthenticationToken(username, password, authorities);
        } else {
            return null;
        }
    }

小結

  1. 很抱歉我依舊沒有為你講解如何將使用者、角色等資料存入資料庫中,本節更多是介紹了Spring Security的驗證流程,但相信你如果真的結合demo2學了下來,你的收穫一定不小
  2. 我們自定義了一個驗證器並將其加入過濾器鏈使黑客baize賬戶獲取兩個許可權並完成登陸
  3. 白澤將在下一篇真正開始將資料存入資料庫並構成第三個demo,敬請期待吧~
  4. 歡迎評論區留言

相關文章