Spring-security提供的认证方式(二)
Spring-security默认提供的AuthenticationProvider
Spring –security 提供了很多AuthenticationProvider的实现了,这里是画出了spring-security默认采用的。
AbstractUserDetailsAuthenticationProvider
实现了AuthenticationProvider提供的authenticate和support方法。
在authenticate方法中做了如下的操作:
1. 根据用户提交的用户名从缓存中查询UserDetails
2. 若没有在缓存中查询到UserDetails,那么就调用retrieveUser检索UserDetails,这个方法是一个抽象方法,在子类中实现;若在子类中没有查询到UserDetails,那么就会抛出UsernameNotFoundException,在AbstractUserDetailsAuthenticationProvider捕获了这个异常并且进行了处理
3. 接着开始检查UserDetails(不论是从缓存中获取的UserDetails,还是检索出来的UserDetails,都要进行检查),主要包括的检测有user是否已经过期,是否已经被锁定等等,在AbstractUserDetailsAuthenticationProvider没有检测用户输入的密码是否正确,在检查这一步调用了抽象
additionalAuthenticationChecks,所有在子类中要实现密码是否匹配的检测
4. 若通过了所有的检测,那么就判断是否这个UserDetails已经放入到了缓存中,若没有那么就放入到缓存中。
5. 最后返回一个包含了用户完整信息的UsernamePasswordAuthenticationToken,包括用户名,密码,权限等等。
DaoAuthenticationProvider
继承了AbstractUserDetailsAuthenticationProvider提供的additionalAuthenticationChecks 和retrieveUser方法
在retrieveUser方法中的操作:调用了UserDetailsService接口的loadUserByUsername方法,当然这里UserDetailsService可以是自己实现,也可以是使用spring-security提供的JdbcImpl
在additionalAuthenticationChecks方法中的操作:主要做的就是密码的检测,判断用户提交的密码是否正确。在DaoAuthenticationProvider中可以设置加密器和salt,默认是没有设置salt,默认加密器是PlaintextPasswordEncoder
添加密码加密器Password Encoder
1. 修改项目中的security.xml:
<bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> <security:authentication-manager> <security:authentication-provider> <security:password-encoder ref="bcryptEncoder"/> <security:jdbc-user-service data-source-ref="securityDataSource"/> </security:authentication-provider> </security:authentication-manager>
2. 修改数据库中的用户的密码为加密后的密码:$2a$10$aEI7rNMQ86QnrDeg1Sjdbux0XULhucRtVUEAtqMoJK0dVgIO0m53G
在spring-security中提供了2个PasswordEncoder接口,实现的方式也不一样,spring-security建议使用org.springframework.security.crypto.password.PasswordEncoder接口,使用这个接口那么就不能设置salt,否则会抛出异常。具体代码查看DaoAuthenticationProvider的setPasswordEncoder方法
SecurityContext ,SecurityContextHolder
SecurityContext:
public interface SecurityContext extends Serializable {
Authentication getAuthentication();
void setAuthentication(Authentication authentication);
}
这个主要是保存了用户认证成功后的认证信息(用户名,密码,权限等)
SecurityContextHolder:系统中所有SecurityContext的持有者,相当于一个SecurityContext对象的容器。SecurityContextHolder有三种策略来保存SecurityContext;
1. ThreadLocalSecurityContextHolderStrategy 这是spring-security默认采用的方式,保存到ThreadLocal中的好处是一次请求到服务器后,我们可以在任何层获取到登录用户的认证现在,不用通过传递request或session
2. InheritableThreadLocalSecurityContextHolderStrategy
3. GlobalSecurityContextHolderStrategy