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
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時刻
需要實現的功能:
-
demo2保留demo1的所有功能,github項目地址
-
自定義一個驗證器加入過濾器鏈(實現:當用戶使用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;
}
}
小結
- 很抱歉我依舊沒有為你講解如何將用戶、角色等數據存入數據庫中,本節更多是介紹了Spring Security的驗證流程,但相信你如果真的結合demo2學了下來,你的收獲一定不小
- 我們自定義了一個驗證器並將其加入過濾器鏈使黑客baize賬戶獲取兩個權限並完成登陸
- 白澤將在下一篇真正開始將數據存入數據庫並構成第三個demo,敬請期待吧~
- 歡迎評論區留言