第一种方案:通过框架密码验证
考虑去掉BCryptPasswordEncoder的配置,直接明文校验,
配置CustomPasswordEncoder
@Component
public class CustomPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
}
WebSecurityConfigurerAdapter继承类中,替换掉原先的BCryptPasswordEncoder 加密方式:
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
return new BCryptPasswordEncoder();
}
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
//auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
auth.userDetailsService(userDetailsService).passwordEncoder(customPasswordEncoder);
}
在单点登录验证方法中,先使用用户名查询到数据库中存储的全部用户信息,使查询出来的密码和框架自动调用查询方法得到的数据库密码通过CustomPasswordEncoder matches校验:
SysUser user = userService.selectUserByUserName(username);
String pwd = user.getPassword();
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, pwd));
实际登录时,手动调用加密方法,加密之后再比对
/**
* 生成BCryptPasswordEncoder密码
*
* @param password 密码
* @return 加密字符串
*/
public static String encryptPassword(String password)
{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.encode(password);
}
但是忽略了每次使用BCryptPasswordEncoder校验都是生成不同的代码。
用户实际登录时,生成的加密密码和数据库存储的密码匹配不上。
发现spring security 在5.x
版本开始为了支持动态的多种密码加密方式:DelegatingPasswordEncoder
委托加密方式
这一块需要继续研究下,暂时搁置。
第二种方案:跳过框架密码验证
使用PreAuthenticatedAuthenticationToken,
SysUser user = userService.selectUserByUserName(username);
String pwd = user.getPassword();
if(user.getUserId() != null){
//存在这个用户
Authentication authentication2 = authenticationManager.authenticate(new PreAuthenticatedAuthenticationToken(username,pwd));
}
配置PreAuthenticatedAuthenticationProvider,处理预验证的验证请求,此身份验证提供程序不会对身份验证请求执行任何检查,因为它们应该已经通过预身份验证。
添加配置:
@Bean
public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider(){
// log.info("Configuring pre authentication provider");
UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper =
new UserDetailsByNameServiceWrapper<>(
userDetailsService);
PreAuthenticatedAuthenticationProvider it = new PreAuthenticatedAuthenticationProvider();
it.setPreAuthenticatedUserDetailsService(wrapper);
return it;
}
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
auth.authenticationProvider(preAuthenticatedAuthenticationProvider());
// auth.userDetailsService(userDetailsService).passwordEncoder(customPasswordEncoder);
}