liyunfu120 2022-04-10 13:03
浏览 106
已结题

Shiro密码验证失败;不匹配预期的凭证

错误信息

2022-04-10 12:41:57.364 ERROR 15608 --- [p-nio-80-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - liyunfu, rememberMe=false] did not match the expected credentials.] with root cause


service层

import org.a

pache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cy.cj.dao.UserDao;
import com.cy.cj.pojo.User;
import com.cy.common.exception.NoValidParamException;

@Service
public class ShrioUserRealm extends AuthorizingRealm {

    @Autowired
    private UserDao userDao;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

    // 基于此方法返回值告诉shiro框架我们采用什么加密算法
    @Override
    public CredentialsMatcher getCredentialsMatcher() {
        HashedCredentialsMatcher cMatcher = new HashedCredentialsMatcher();
        cMatcher.setHashAlgorithmName("MD5");
        cMatcher.setHashIterations(5);

        return cMatcher;
    }

    // 此方法负责认证信息获取以及封装
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1、获取用户登陆信息;
        
        UsernamePasswordToken uToken = (UsernamePasswordToken) token;

        String username = uToken.getUsername();
        // 2、基于用户查询数据库获取对象信息并进行判定
        // 2.1;获取用户对象
        if(username==null || username=="") {
            throw new NoValidParamException("请输入用户名");
        }
        User user = userDao.findShiroUserByUsername(username);
        // 2.2;验证用户对象是否存在
        if(user==null) {
            throw new UnknownAccountException();
        }
        // 2.3:检查用户是否被禁用
        if(user.getValid()==0) {
            throw new LockedAccountException();
        }
        
        System.out.println(user);
        
        
        // 3、封装用户信息并返回
        ByteSource byteSource = ByteSource.Util.bytes(user.getSalt().getBytes());//将盐值转换为info可接收的byteSource类型
        
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                uToken.getUsername(), //principal用户身份
                user.getPassword(), //hashedcredentials已加密的密码
                byteSource, //credentialsSalt盐值
                this.getName());
        
        
        return info;
    }

}

controller层

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cy.cj.service.UserService;
import com.cy.common.vo.JsonResult;
import com.cy.common.vo.UserPasswordVo;
import com.cy.common.vo.UserRoleVo;

@Controller
@RequestMapping("/user/")
@ResponseBody
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("doLogin")
    public JsonResult doLogin(String username, String password) {
        //获取subject对象
        Subject subject = SecurityUtils.getSubject();
        //提交用户请求
        UsernamePasswordToken token = new UsernamePasswordToken();
        token.setUsername(username);
        token.setPassword(password.toCharArray());
        
        subject.login(token);// 将token提交给SecurityUtils安全管理器;

        return new JsonResult("login OK");
    }
}

数据层

@Mapper
public interface UserDao {

    User findShiroUserByUsername(String username);
}
<mapper namespace="com.cy.cj.dao.UserDao">

    <!-- @Select("select * from tb_user where username=#{username}")
    User findShiroUserByUsername(String username);-->
    <select id="findShiroUserByUsername" resultType="com.cy.cj.pojo.User">
    select * from tb_user where username=#{username}
    
    </select>
</mapper>

shiro配置

package com.cy.cj.Config;

import java.util.LinkedHashMap;

import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //配置文件交给Spring管理
public class SpringShiroConfig {
    
    
    //配置Shiro中核心对象,安全管理器
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm) {
        
        
        
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;    
    }
    
    //配置ShiroFilterFactoryBean对象
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        //
        ShiroFilterFactoryBean sBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        sBean.setSecurityManager(defaultWebSecurityManager);
        //设置登陆页面URL
        sBean.setLoginUrl("/login");
        
        //设置过滤规则
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        //静态资源允许匿名访问
        map.put("/assets/**", "anon");
        map.put("/bower_components/**", "anon");
        map.put("/build/**", "anon");
        map.put("/css/**", "anon");
        map.put("/dist/**", "anon");
        map.put("/images/**", "anon");
        map.put("/js/**", "anon");
        map.put("/plugins/**", "anon");
        map.put("/user/doLogin","anon");
        //除了匿名访问的资源,其它都要认证("authc")后访问
        map.put("/**", "authc");
        
        sBean.setFilterChainDefinitionMap(map);
        return sBean;
    }
    
    
}


保存的密码方法

package com.cy.cj.service.Impl;

import java.util.List;
import java.util.UUID;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import com.cy.cj.annotation.CacheAspect;
import com.cy.cj.annotation.clearCache;
import com.cy.cj.dao.UserDao;
import com.cy.cj.dao.UserRoleDao;
import com.cy.cj.service.UserService;
import com.cy.common.exception.DeleteFailException;
import com.cy.common.exception.InsertFailException;
import com.cy.common.exception.LoginFailException;
import com.cy.common.exception.NoSuchException;
import com.cy.common.exception.NoValidParamException;
import com.cy.common.exception.SelectFailException;
import com.cy.common.exception.UpdateFailException;
import com.cy.common.vo.PageObject;
import com.cy.common.vo.UserPasswordVo;
import com.cy.common.vo.UserRoleVo;
import com.cy.common.vo.UserVo;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserRoleDao userRoleDao;

    @clearCache(dataKey="userData")
    @Override
    public Long addUserRoles(UserRoleVo userRoleVo) {
        Long row = null;
        if (userRoleVo == null) {
            throw new NoValidParamException("无效数据");
        }

        if (userRoleVo.getRole_ids() == null || userRoleVo.getRole_ids().length < 1) {
            throw new NoValidParamException("至少分配一个角色");
        }
        // MD5加密
        String salt = UUID.randomUUID().toString();

        DigestUtils.md5Digest((salt + userRoleVo.getPassword()).getBytes());

        SimpleHash sh = new SimpleHash("MD5", salt, userRoleVo.getPassword(), 5);
        String hashpassword = sh.toHex();

        userRoleVo.setSalt(salt);
        userRoleVo.setPassword(hashpassword);

        try {
            row = userDao.addUser(userRoleVo);
        } catch (Exception e) {
            throw new InsertFailException("数据插入失败");
        }
        if (row == null || row == 0) {
            throw new InsertFailException("数据0条数据");
        }

        Long rows = null;
        try {
            rows = userRoleDao.addUserRoles(userRoleVo.getId(), userRoleVo.getRole_ids());
        } catch (Exception e) {
            throw new InsertFailException("数据插入失败");
        }
        if (rows == null || rows == 0) {
            throw new InsertFailException("数据0条数据");
        }

        return row;
    }
}

  • 写回答

1条回答 默认 最新

  • liyunfu120 2022-04-10 18:15
    关注

    跟断点跟到问题了,原来加密后的密码不对,才发现写的密码和盐值参数位置不对;
    太难了!!!

    img

    img

    img

    img

    评论

报告相同问题?

问题事件

  • 系统已结题 4月18日
  • 修改了问题 4月10日
  • 创建了问题 4月10日

悬赏问题

  • ¥20 msconfig开启安全引导后重启电脑黑屏
  • ¥15 对email表单做了一般邮箱正则校验,现在需要额外输入为hotmail或outlook、gmail时做特定邮箱校验,不符合提示出来。并且保证不影响其他正确的邮箱格式通过校验,通过不会提示。
  • ¥20 Win11,bitblocker密钥恢复失败
  • ¥15 stm32 cubemx配置sdram,初始化后无法读写sdram
  • ¥100 上位机到dtu再到485继电器模块 目前结束命令有百分之2左右概率执行失败求指导
  • ¥15 ifcopenshell库在vs2019下的配置
  • ¥15 whql认证的windows硬件开发者账号个人验证不匹配问题
  • ¥15 色彩分析仪sensor
  • ¥15 求网页搭建平台会的联系我
  • ¥15 尼康光电绝对值编码器(相关搜索:绝对值|编码器)