背景:本来有一个web系统,使用的是Spring Security,有自己的用户表。现在给的需求是集成另一个内部系统,在系统间实现免密登录跳转。继承的过程一切从简,对方直接把用户表给我了,使用多数据源操作,同时读2个用户表。
读多数据源我参考的是这篇文章:https://wangsong.blog.csdn.net/article/details/107330001
@Bean @Primary public UserDetailsService userDetailsService1() { return new UserDetails1ServiceImpl(sysUserService, dataService); } @Bean public UserDetailsService userDetailsService2() { return new UserDetails2ServiceImpl(userInfoService); } /** * 手动创建AuthenticationManager,可以声明2个以上的UserDetailsService * 默认先用@Primary注解的bean查询用户,没查到在去第二个bean查询用户 * * @return AuthenticationManager * @throws Exception / */ @Bean protected AuthenticationManager authenticationManager() throws Exception { // 用户表1 DaoAuthenticationProvider dao1 = new DaoAuthenticationProvider(); dao1.setUserDetailsService(userDetailsService1()); dao1.setPasswordEncoder(passwordEncoder()); // 用户表2 DaoAuthenticationProvider dao2 = new DaoAuthenticationProvider(); dao2.setUserDetailsService(userDetailsService2()); dao2.setPasswordEncoder(passwordEncoder()); List<AuthenticationProvider> providers = new ArrayList<>(); providers.add(dao1); providers.add(dao2); return new ProviderManager(providers); }
有2个service实现了2个UserDetailsService接口,每个service读取一张用户表。并且同时注册给AuthenticationManager,在需要查询用户时,优先查询@Primary注解的Service,没有在查第二个service。
好了,我们继续吐槽... 我接入的内部系统的用户表密码居然是明文存储的,使用原来的login方法各种报错,我只能再复制一份login方法,开始改造,登录入口虽然不一样,但登录功能后的逻辑全是一样的。改造过程中出现的异常主要有2面两个:
1. Encoded password does not look like BCrypt
错误原因:原系统都是BCryptPasswordEncoder加密的密码,前端传的是加密串,数据库存的也是加密串。而我介入的内部系统全是未加密的字符串,所以就报这样的错误。
解决办法:我把用户表2的数据查询出来之后,把密码进行了加密,用户调动login方法的密码也加密了。接下来又报了下面的错误。
2. Bad credentials
这个错误肯定是凭证错误,可以理解为用户名或密码错误。我们初步判断是密码机加密到那个步骤出错了。后来翻阅资料发现原来是我多做了一步。看下面测试。
@Autowired private PasswordEncoder passwordEncoder; @Test public void checkPassword(){ // 用户输入的登录密码,未加密 String password1 = "123456"; // 数据库里存的密码,加密字符串 String password2 = passwordEncoder.encode("123456"); if (!passwordEncoder.matches(password1, password2)) { System.out.println("密码错误"); } else { System.out.println("验证通过"); } }
这个测试说明,用户登录时密码是不需要加密的。我回看原来的login方法,发现也是拿到密文密码再解密后使用的。好吧,我多此一举了,把登录密码直接使用后,登录正常了。