第一种方案:通过框架密码验证

考虑去掉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);
    }