spring security的核心功能:认证和授权,认证就是身份验证(你是谁?),授权就是访问控制(你可以做什么?),同时他还提供很多安全管理的周边功能。在Spring Security的架构设计中,认证(Authentication)和授权(Authorization)是分开的,本篇文章主要涉及认证相关的功能和原理介绍。
2.认证核心组件 2.1 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;
}
2.2 AuthenticationManager
authenticate方法用来做认证,返回Authentication表示认证成功,抛出异常表示用户输入无效的凭证,返回null表示不能确定
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
2.3 ProviderManager
ProviderManager是AuthenticationManager的实现类,ProviderManager管理众多AuthenticationProvider实例(详见2.4节),AuthenticationProvider会有一个supports方法,用来判断当前AuthenticationProvider是否支持此次认证请求。
ProviderManager的大致认证流程就是遍历众多AuthenticationProvider实例(例如有的是表单登陆,有的是短信验证码登陆)。
//省略部分代码
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
private AuthenticationEventPublisher eventPublisher;
private List providers;
private AuthenticationManager parent;
private boolean eraseCredentialsAfterAuthentication;
public ProviderManager(AuthenticationProvider... providers) {
this(Arrays.asList(providers), (AuthenticationManager)null);
}
public ProviderManager(List providers) {
this(providers, (AuthenticationManager)null);
}
public ProviderManager(List providers, AuthenticationManager parent) {
}
//核心部分,省略部分代码
public Authentication authenticate(Authentication authentication) throws AuthenticationExceptio {
Class extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
int currentPosition = 0;
int size = this.providers.size();
for (AuthenticationProvider provider : getProviders()) {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
}
//如果providers都不能处理,由parent处理
if (result == null && this.parent != null) {
// Allow the parent to try.
try {
parentResult = this.parent.authenticate(authentication);
result = parentResult;
}
catch (AuthenticationException ex) {
parentException = ex;
lastException = ex;
}
}
if (result != null) {
if (this.eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
//擦除密码,发布事件
((CredentialsContainer) result).eraseCredentials();
}
if (parentResult == null) {
this.eventPublisher.publishAuthenticationSuccess(result);
}
return result;
}
}
}
2.4 AuthenticationProvider
AuthenticationProvider有点类似AuthenticationManager,但是多了一个supports方法用来判断是否支持给定的Authentication类型
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class> authentication);
}
2.5 UserDetails
规范开发者自定义用户对象
public interface UserDetails extends Serializable {
//返回当前账户具备的权限
Collection extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
2.6 UserDetailsService
负责提供用户数据源,提供查询用户的方法
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
3. Filter
在Spring Security中,认证和授权都是基于过滤器来完成的,过滤器通过FilterChainProxy来统一代理,然后将FilterChainProxy嵌入到web项目的原生过滤器中。FilterChainProxy本身通过Spring框架提供的DelegatingFilterProxy整合到原生过滤器链中。



