Spring Security集成异常总结

  背景:本来有一个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方法,发现也是拿到密文密码再解密后使用的。好吧,我多此一举了,把登录密码直接使用后,登录正常了。

原文地址:https://www.cnblogs.com/huanshilang/p/13589544.html