错误信息
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;
}
}