第一次使用shiro踩坑 输入正确密码登录也会

shiro输入正确密码也会登录失败

shiro整合springBoot后登录一直失败的原因

最后发现是存入数据库的密码密文在shiro比较之前会进行一次base64的转换

上代码

shiro配置

@Configuration
public class ShiroConfig {


    /**
     * 加密算法
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        //加密对象
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //加密方法
        matcher.setHashAlgorithmName("md5");
        //加密次数
        matcher.setHashIterations(2);
        //加密编码方式
        matcher.setStoredCredentialsHexEncoded(false);

        return matcher;
    }

    /**
     * 自定义realm
     * @return
     */
    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myRealm;
    }



    /**
     * 安全管理器
     * @return
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        return securityManager;
    }


    /**
     * shiro
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        Map<String,String> filterChainDefinitionMap = new HashMap<>(16);// 配置不会被拦截的链接 顺序判断,因为前端模板采用了 thymeleaf,
        // 这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码 Shiro 已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        // 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        // authc:所有 url 都必须认证通过才可以访问; anon:所有 url 都都可以匿名访问-->
        filterChainDefinitionMap.put("/user/login","anon");
        filterChainDefinitionMap.put("/user/register","anon");
        filterChainDefinitionMap.put("/user/login_page","anon");
        //所有请求都认证
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不设置默认会自动寻找 Web 工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 管理shirobean的生命周期
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    /**
     * aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    /**
     * aop生效
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

}

自定义realm


@Component
@SuppressWarnings("all")
public class MyRealm extends AuthorizingRealm {

    @Autowired
    EmployeeMapper employeeMapper;

    PasswordService passwordService = new DefaultPasswordService();

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();

        SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();

        return simpleAuthenticationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String employeeName = (String) authenticationToken.getPrincipal();

         String passWord = null;
        if (StringUtils.isNumeric(employeeName)&&employeeName.length()!=11) {  //判断为数字且不是手机号
            Integer employeeId = Integer.valueOf(employeeName);
            passWord = getPwdByid(employeeId);
        }else if(StringUtils.isNumeric(employeeName)&&employeeName.length()==11){  //判断为手机号
            passWord = getPwdByPhone(employeeName);
        }else {                                                                //其他所有情况判断为邮箱
            passWord = getPwdByEmail(employeeName);
        }

        if (passWord==null){
            return null;
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(employeeName,passWord,getName());
        return info;
    }

    /**
     * 根据id查密码
     * @param employeeId
     * @return
     */
    public String getPwdByid(int employeeId){
        Employee employee = employeeMapper.selectByPrimaryKey(employeeId);
        if (employee==null){
            return null;
        }
        return employee.getPassword();
    }

    /**
     * 根据手机号查密码
     * @param phone
     * @return
     */
    public String getPwdByPhone(String phone){
        Employee employee = employeeMapper.selectByPhone(phone);
        if (employee==null){
            return null;
        }
        return employee.getPassword();
    }

    /**
     * 根据邮箱查密码
     * @param email
     * @return
     */
    public String getPwdByEmail(String email){
        Employee employee = employeeMapper.selectByEmail(email);
        if (employee==null){
            return null;
        }
        return employee.getPassword();
    }

    public Employee getEmpByPhone(String phone){
        Employee employee = employeeMapper.selectByPhone(phone);
        if (employee==null){
            return null;
        }
        return employee;
    }

    public int register(Employee employee){
        employee.setPassword(new Md5Hash(employee.getPassword(),null,2).toString());
        employeeMapper.insert(employee);
        return 1;

    }

在存入数据库时调用加密时用的 toString() 方法

 public int register(Employee employee){
        employee.setPassword(new Md5Hash(employee.getPassword(),null,2).toString());
        employeeMapper.insert(employee);
        return 1;

    }

在这里插入图片描述
存入数据库的时 123456 加密后 用toString获取的密文

此时登录一直无法通过

查看源码
第一次使用shiro踩坑 输入正确密码登录也会_第1张图片
第一次使用shiro踩坑 输入正确密码登录也会_第2张图片
在这里插入图片描述
因为配置的时 false

第一次使用shiro踩坑 输入正确密码登录也会_第3张图片
如果配成true 则会走Hex的方式

toString() 和 Hex 要一致
toBase64() he 上面一致

最后导致始终无法登录

## 解决方法
第一次使用shiro踩坑 输入正确密码登录也会_第4张图片
配置改为true

或者
第一次使用shiro踩坑 输入正确密码登录也会_第5张图片
toString() 改成 toBase64()

你可能感兴趣的:(第一次使用shiro踩坑 输入正确密码登录也会)