package com.bcxin.sp.shiro.service; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.bcxin.sp.config.exception.BusinessException; import com.bcxin.sp.manager.AsyncManager; import com.bcxin.sp.manager.factory.AsyncFactory; import com.bcxin.sp.work.entity.domain.sys.ConfigMenu; import com.bcxin.sp.work.entity.domain.sys.Region; import com.bcxin.sp.work.entity.domain.user.LoginUserDetail; import com.bcxin.sp.work.entity.domain.user.User; import com.bcxin.sp.work.service.log.AuditLogService; import com.bcxin.sp.work.service.sys.ConfigMenuService; import com.bcxin.sp.work.service.sys.RegionService; import com.bcxin.sp.work.service.user.UserService; import com.bcxin.sp.work.util.Const.*; import com.bcxin.sp.work.util.MessageUtils; import com.bcxin.sp.work.util.ServletUtils; import com.bcxin.sp.work.util.StringUtil; import com.bcxin.sp.work.util.WebUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.util.List; import java.util.Map; /** * 登录校验方法 * * @author task */ @Component public class SysLoginService { @Resource private RegionService regionService; @Resource private UserService userService; @Resource private AuditLogService auditLogService; @Resource private ConfigMenuService configMenuService; //记录登录次数和时长 private static Map LT = Maps.newHashMap(); //上限次数标识头 private final static String LIMIT_NUM_HEAD = "LIMIT-NUM-HEAD-"; //上限时间标识头 private final static String LIMIT_TIME_HEAD = "LIMIT-TIME-HEAD-"; /** * 登录 */ public User login(String username, String password) { if (isLoginLimit(username)) { throw new BusinessException("登录操作过于频繁,系统已锁定目标用户,请10分钟后重试!"); } // 用户名或密码为空 错误 if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { recordLoginMsg(username); throw new BusinessException("用户名或密码为空"); } // 密码如果不在指定范围内 错误 if (password.length() < UserConst.PASSWORD_MIN_LENGTH || password.length() > UserConst.PASSWORD_MAX_LENGTH) { recordLoginMsg(username); throw new BusinessException("密码格式错误"); } // 用户名不在指定范围内 错误 if (username.length() < UserConst.USERNAME_MIN_LENGTH || username.length() > UserConst.USERNAME_MAX_LENGTH) { recordLoginMsg(username); throw new BusinessException("用户名格式错误"); } return login(username,password,true); } public User login(String username, String password,boolean validatePassword){ // 查询用户信息 User dbUser = userService.findByUserName(username); if (dbUser == null) { recordLoginMsg(username); throw new BusinessException("用户名不存在"); } if (!dbUser.isActive()) { recordLoginMsg(username); throw new BusinessException("用户名未激活"); } if(!dbUser.getPassword().equalsIgnoreCase(password.trim())) { recordLoginMsg(username); throw new BusinessException("密码不正确"); } if (StrUtil.isNotEmpty(dbUser.getProvince())) { Region region = regionService.findById(Long.parseLong(dbUser.getProvince())); dbUser.setProvincename(region.getFullName()); } if (StrUtil.isNotEmpty(dbUser.getCity())) { Region region = regionService.findById(Long.parseLong(dbUser.getCity())); dbUser.setCityname(region.getFullName()); } if (StrUtil.isNotEmpty(dbUser.getArea())) { Region region = regionService.findById(Long.parseLong(dbUser.getArea())); dbUser.setAreaname(region.getFullName()); } ServletUtils.getRequest().getSession().setAttribute(GlobalConst.LOGIN_USER, dbUser); ServletUtils.getRequest().getSession().setAttribute(GlobalConst.LOGIN_USER_PROVINCE, dbUser.getProvince()); LoginUserDetail detail = new LoginUserDetail(); detail.setUserId(dbUser.getUsername()); detail.setUserName(dbUser.getRealName()); detail.setOrganization(dbUser.getDepart()); detail.setTerminalID(WebUtil.getIP(ServletUtils.getRequest())); ServletUtils.getRequest().getSession().setAttribute(GlobalConst.LOGIN_USER_DETAIL, detail); /* 初始化菜单 */ List menuList = configMenuService.getUserMenu(dbUser); List menuLevelOneList = Lists.newLinkedList(); Map> menuLevelTwoMap = Maps.newLinkedHashMap(); for (ConfigMenu menu : menuList) { if (DictConst.MENULEVEL_ONE.equals(menu.getMenuLevel())) { menuLevelOneList.add(menu); } if (DictConst.MENULEVEL_TWO.equals(menu.getMenuLevel())) { List twoList = menuLevelTwoMap.get(menu.getParentId()); if (CollectionUtil.isNotEmpty(twoList)) { twoList.add(menu); menuLevelTwoMap.put(menu.getParentId(), twoList); } else { menuLevelTwoMap.put(menu.getParentId(), Lists.newArrayList(menu)); } } } ServletUtils.getRequest().getSession().setAttribute(GlobalConst.LOGIN_USER_MENU_LEVEL_ONE, menuLevelOneList); ServletUtils.getRequest().getSession().setAttribute(GlobalConst.LOGIN_USER_MENU_LEVEL_TWO, menuLevelTwoMap); /* 审计日志 */ // auditLogService.auditLog(DictConst.OP_LOGIN, null, DictConst.Y); AsyncManager.me().execute(AsyncFactory.recordAuditLog(DictConst.OP_LOGIN, null, DictConst.Y,detail)); /* 记录登录log */ // userService.logLogin(dbUser); AsyncManager.me().execute(AsyncFactory.recordLoginLog(dbUser)); //删除历史登录失败记录 deleteLoginLimit(username); return dbUser; } /** * 是否达到登录限制的上限 * * @author ZXF * @create 2020/10/14 0014 11:25 * @version * @注意事项 */ private static boolean isLoginLimit(String username) { String num = LT.get(LIMIT_NUM_HEAD + username); if (StringUtil.isEmpty(num)) { return false; } String time = LT.get(LIMIT_TIME_HEAD + username); long surplus = (System.currentTimeMillis() - Long.parseLong(time)); //大于5分钟 if (surplus >= 600000) { //删除历史登录失败记录 deleteLoginLimit(username); return false; } //在5分钟之内,判断已记录次数 if (Integer.parseInt(num) == 5) { return true; } return false; } /** * 登录失败记录登录次数 * * @author ZXF * @create 2020/10/14 0014 11:26 * @version * @注意事项 */ private static void recordLoginMsg(String username) { String num = LT.get(LIMIT_NUM_HEAD + username); //如果没记录,就重新初始化设置 if (StringUtil.isEmpty(num)) { LT.put(LIMIT_NUM_HEAD + username, "1"); LT.put(LIMIT_TIME_HEAD + username, String.valueOf(System.currentTimeMillis())); return; } //有记录的重新叠加失败次数 LT.put(LIMIT_NUM_HEAD + username, String.valueOf(Integer.parseInt(num) + 1)); } /** * 登录成功删除登录上限记录 * * @author ZXF * @create 2020/10/14 0014 11:26 * @version * @注意事项 */ private static void deleteLoginLimit(String username) { LT.remove(LIMIT_NUM_HEAD + username); LT.remove(LIMIT_TIME_HEAD + username); } }