Spring Security-数据库管理
当一个用户登陆时,会先执行身份认证,如果身份认证未通过则会要求用户重新认证;当用户身份认证通过后,则会调用角色管理器,判断用户是否可以访问。这里,如果要实现使用数据库管理用户及权限,就需要自定义用户登陆功能,而SpringSecurity已经为我们提供好了接口。
public interface UserDetailsService {
// ~ Methods
// =========================================================================
/**
* Locates the user based on the username. In the actual implementation, the search
* may possibly be case sensitive, or case insensitive depending on how the
* implementation instance is configured. In this case, the <code>UserDetails</code>
* object that comes back may have a username that is of a different case than what
* was actually requested..
*
* @param username the username identifying the user whose data is required.
*
* @return a fully populated user record (never <code>null</code>)
*
* @throws UsernameNotFoundException if the user could not be found or the user has no
* GrantedAuthority
*/
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
UserServiceDetails只有一个方法loadUserByUsername,根据方法名可以初步判断功能为根据用户名返回用户信息,而它的返回值也是一个接口。
public interface UserDetails extends Serializable {
// ~ Methods
// =========================================================================
* Returns the authorities granted to the user. Cannot return <code>null</code>.
Collection<? extends GrantedAuthority> getAuthorities();//权限集合,存储了用户所有的权限
String getPassword();
String getUsername();
boolean isAccountNonExpired();//账户是否过期
boolean isAccountNonLocked();//账户是否被锁定
boolean isCredentialsNonExpired();//证书时候过期
boolean isEnabled();//账户是否有效
}
其中后四个判断方法,任何一个返回false,则用户被视为无效。注意Authentication和UserDetails的区分,Authentication对象才是SpringSecurity使用的进行安全访问控制用户信息的安全对象,实际上Authentication对象有未认证和已认证的两种状态,在作为参数传入认证管理器的时候,它是一个未认证的对象,它从客户端获取用户的身份信息,如用户名密码,可以是从一个登陆页面也可以是从cookie中获取,并由系统自动构成一个Authentication对象。而上面的UserDetails它代表的是一个用户安全信息的源,这个源可以是从数据库,LDAP服务器,CA中心返回。SpringSecurity要做的就是将等待认证的Authentication对象和UserDetails对象进行匹配,成功后,将UserDetails中的用户信息拷贝到Authentication中,组成一个完整的Authentication对象与其他组件进行共享。UserDetails既可以从数据库中返回,也可以LDAP等中返回,这取决与系统中使用什么来存储用户信息和权限以及相应的用户提供者。
public interface Authentication extends Principal, Serializable {
// ~ Methods
================================================================================================
Collection<? extends GrantedAuthority> getAuthorities();//权限集合
Object getCredentials();//获取凭证
Object getDetails();//获取认证一些额外信息
Object getPrincipal();//过去认证的实体
boolean isAuthenticated();//是否认证通过
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
当我们需要使用数据库管理用户时,我们需要手动实现UserDetailsService接口里面的loadUserByUsername方法,这就需要准备一下几张表。它们分别是用户表,角色表,权限表,用户和角色关系表,权限和角色关系表。UserDetails中的用户状态通过用户表里的属性去填充,UserDetails中的权限集合则是通过用户表,权限表,用户和角色关系表,权限和角色关系表构成的RBAC模型来提供。