AuthenticationManager是一個接口:
public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException; }
ProviderManager是AuthenticationManager的實現類:
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean { ...... private List<AuthenticationProvider> providers = Collections.emptyList(); ...... public Authentication authenticate(Authentication authentication) throws AuthenticationException { ...... } }
從以上代碼中可以看到ProviderManager有一個List<AuthenticationProvider> providers成員變量。AuthenticationProvider也是一個接口:
public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); }
可以看到包含兩個成員函數authenticate和supports。
接下來我們看一下整個的認證過程:
認證是通過AuthenticationManager的authenticate函數實現的。也就是通過AuthenticationManager實現類ProviderManager的authenticate函數認證,ProviderManager的authenticate函數會輪訓ProviderManager的List<AuthenticationProvider> providers成員變量,如果該providers中如果有一個AuthenticationProvider的supports函數返回true,那么就會調用該AuthenticationProvider的authenticate函數認證,如果認證成功則整個認證過程結束。如果不成功,則繼續使用下一個合適的AuthenticationProvider進行認證,只要有一個認證成功則為認證成功。
如果上述過程沒有認證成功,且該ProviderManager的成員變量AuthenticationManager parent不為null,那么會使用該parent繼續認證。一般不會用到該AuthenticationManager parent,稍微留意以下即可。
另:Authentication
可以看到authenticate函數返回Authentication,Authentication是一個接口,通過該接口可以獲得用戶相信信息,代碼:
public interface Authentication extends Principal, Serializable { Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }
另:DaoAuthenticationProvider
<authentication-provider>默認實例化AuthenticationProvider的一個實現:DaoAuthenticationProvider。DaoAuthenticationProvider通過接口UserDetailsService的實現類從內存或DB中獲取用戶信息UserDetails(UserDetails十分類似Authentication,也是一個接口,但是與Authentication用途不同,不要搞混)。DaoAuthenticationProvider通過函數authenticate比較入參authentication與UserDetails是否相符,來判斷用戶是否可以登錄。如果相符,會將獲得的UserDetails中的信息補全到一個Authentication實現類,並將該實現類作為認證實體返回。以后便可以通過當前上下文的認證實體Authentication獲取當前登錄用戶的信息。
UserDetails代碼:
public interface UserDetails extends Serializable { Collection<? extends GrantedAuthority> getAuthorities(); String getPassword(); String getUsername(); boolean isAccountNonExpired(); boolean isAccountNonLocked(); boolean isCredentialsNonExpired(); boolean isEnabled(); }
UserDetails和Authentication區別:
接口 | 目的 |
Authentication | 它存儲安全實體的標識、密碼以及認證請求 |
UserDetails | 為了存儲一個安全實體的概況信息,包含名 |