SpringSecurity(一、二、三)身份認證的用戶名和密碼是啟動服務器自動生成的,或者是代碼中寫死的,存儲在內存中。而實際項目中應該從動態的從數據庫中獲取進行身份認證。
1.實現流程:
(1)關注 UserDetailsService 、 UserDetails 接口
(2)自定義一個 UserDetailsService 接口的實現類 CustomUserDetailsService ,實現該接口中的loadUserByUsername 方法 ,通過該方法定義獲取用戶信息的邏輯。
(3)
從數據庫獲取到的用戶信息封裝到 UserDetail 接口的實現類中(Spring Security 提供了一個org.springframework.security.core.userdetails.User 實現類封裝用戶信息)。
(4)如果未獲取到用戶信息,則拋出異常 throws UsernameNotFoundException
public interface UserDetails extends Serializable {
//此用戶可訪問的資源權限
Collection<? extends GrantedAuthority> getAuthorities();
//用戶名
String getPassword();
//密碼
String getUsername();
//帳戶是否過期(true 未過期,false 已過期) boolean isAccountNonExpired();
//帳戶是否被鎖定(true 未鎖定,false 已鎖定),鎖定的用戶是可以恢復的 boolean isAccountNonLocked();
//密碼是否過期(安全級別比較高的系統,如30天要求更改密碼,true 未過期,false 過期) boolean isCredentialsNonExpired();
//帳戶是否可用(一般指定是否刪除,系統一般不會真正的刪除用戶信息,而是假刪除,通過一個狀態碼標志 用戶被刪除)刪除的用戶是可以恢復的 boolean isEnabled();
}
2.自定義CustomUserDetailsService類實現UserDetailsService接口
/** * 查詢數據庫中的用戶信息 */ @Component("CustomUserDetailsService") public class CustomUserDetailsService implements UserDetailsService { Logger logger=LoggerFactory.getLogger(CustomUserDetailsService.class); @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.info("請求認證的用戶名:"+username); //1.通過請求的用戶名去數據庫中查詢用戶信息 if (!"zcc".equals(username)){ throw new UsernameNotFoundException("用戶名或密碼錯誤"); } //假設當前這個用戶在數據庫中存儲的密碼是123 String password=bCryptPasswordEncoder.encode("123"); //2.查詢該用戶所擁有的權限 // 3.封裝用戶信息: username用戶名,password數據庫中的密碼,authorities資源權限標識符 // SpringSecurity 底層會校驗是否身份合法。 return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN")); } }
3.重構安全配置類SpringSecurityConfig
注入 CustomUserDetailsService 在confifigure(AuthenticationManagerBuilder auth) 方法中指定認證方式
@Autowired CustomUserDetailsService customUserDetailsService; /** * 認證管理器: * 1、認證信息提供方式(用戶名、密碼、當前用戶的資源權限) * 2、可采用內存存儲方式,也可能采用數據庫方式等 * * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //基於內存存儲認證信息 存儲的密碼必須是加密后的 不然會報錯:There is no PasswordEncoder mapped for the id "null" //auth.inMemoryAuthentication().withUser("zcc").password("123").authorities("ADMIN"); /*String password = bCryptPasswordEncoder().encode("123"); logger.info("加密后的密碼:" + password); auth.inMemoryAuthentication().withUser("zcc").password(password).authorities("ADMIN");*/ // 指定使用自定義查詢用戶信息來完成身份認證 auth.userDetailsService(customUserDetailsService); }
完整代碼地址:https://gitee.com/zhechaochao/security-parent.git
