用户登录错误次数限制、并实现:错误登录次数、登录错误间隔时间、封禁时间,参数的可配

1、可配参数说明:

错误登录次数:用户可“连续”输入错误的次数;

登录错误间隔时间:第一次错误~最后一次错误的间隔时间(此处用分钟做计算);

封禁时间:登录错误次数达到上限后,禁止用户登录的时长(此处用分钟做计算);


2、表设计:

h_login_miss:记录登录次数和状态-主表

h_login_log:记录登录信息-附表-主要记录了每个用户的登录时间(排除“登录错误间隔时间”之前的错误登录记录),用于实现(登录错误间隔时间的可配化--如果需求是“每日错误登录限制”,此表可省略

CREATE TABLE `h_login_miss` (

  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `employee_id` bigint(19) NOT NULL COMMENT '用户id',
  `miss_number` int(11) unsigned zerofill DEFAULT NULL COMMENT '登录失败次数(登录成功就清0 失败就+1)',
  `miss_time` datetime DEFAULT NULL COMMENT '锁定登录时间:这个时间如果大于当前时间 则不能登录',
  `miss_flag` char(1) DEFAULT NULL COMMENT '锁定标志:0未锁定状态  1代表锁定状态 ',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='登录错误限制表';

CREATE TABLE `h_login_log` (

  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `employee_id` bigint(19) NOT NULL COMMENT '用户id',
  `flag` char(1) DEFAULT NULL COMMENT '登录状态(0:登录成功  1:登录失败)',
  `ip_address` varchar(255) DEFAULT NULL COMMENT 'ip地址',
  `login_time` datetime DEFAULT NULL COMMENT '登录时间',
  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=261 DEFAULT CHARSET=utf8 COMMENT='登录记录表';


3、代码:

此处只写出MVC层代码和核心业务代码;(--使用切面,在登录模块做验证)

@Aspect
@Configuration
public class LoginAspect extends BaseController{
    private final Logger logger = Logger.getLogger(this.getClass());

    // 定义切点Pointcut
    @Pointcut("execution(* com.credit.controller.shiro.LoginController.loginPost(String , String , String ,*)) && args(username,password,code,session)")
    public void excudeService(String username, String password, String code, HttpSession session) {}


    /**
     *
     * @TitledoAround
     * @Description: 环绕触发
     */
    @Around("excudeService(username,  password, code,session)")
    public Object doAround(ProceedingJoinPoint pjp,String username, String password, String code, HttpSession session) throws Throwable {
        Boolean flag = true;
        Object resultStr = null;

        if (StringUtils.isBlank(username)) {
            return renderError("用户名不能为空");
        }
        if (StringUtils.isBlank(password)) {
            return renderError("密码不能为空");
        }
        //验证是否含可能登录
        //此处调用的boot代码,可直接更改为,方法调用(具体方法在下面的代码中)
        String url = FileHelpper.map.get("url.userUrl")+ FileHelpper.map.get("loginMiss.judgeMiss");
        StringBuffer str = new StringBuffer();
        str.append("loginName=" + username);

        logger.info("请求参数:"+url+"?"+str);
        String result = HttpReqUtil.sendPost(url,str.toString());
        logger.info("返回结果集:"+result);
        if (StringUtils.isBlank(result)){
            return renderError("不存在该用户");
        }
        JSONObject jsonObject = JSONObject.parseObject(result);
        Integer resultNo = jsonObject.getInteger("resultNo");
        if (resultNo == 0) {
            resultStr = pjp.proceed();//登录目标方法 result的值就是被拦截方法的返回值
            //获取request
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            //设置IP地址--登录成功后记录用户登录数据
            String ipAddress = IPUtils.getIpAddr(request);
            String url2 = FileHelpper.map.get("url.userUrl")+ FileHelpper.map.get("loginMiss.importMiss");
            StringBuffer str2 = new StringBuffer();
            str2.append("loginName=" + username);
            str2.append("&flag=" + (((Result)resultStr).getResultNo()==0));
            str2.append("&ipAddress=" + ipAddress);
            logger.info("请求参数:"+url2+"?"+str2);
            String result2 = HttpReqUtil.sendPost(url2,str2.toString());
            logger.info("返回结果集:"+result2);

            return resultStr;
        }else {
            return renderError("不存在该用户");
        }
    }

}
/**
 * 登录错误或正确处理
 * @param employeeId
 * @param flag  true正确   false用户输入错误
 * @return
 */
@Override
public int importMiss(Long employeeId,Boolean flag) {
    LoginMiss login = loginMissMapper.findLoginByEmployeeId(employeeId);
    if (login == null) {
        if (flag) {
            addLoginMiss(employeeId, 0);
        } else {
            addLoginMiss(employeeId, 1);
        }
    }

    if (flag) {
        login.setMissFlag("0");
        login.setMissNumber(0);
        login.setMissTime(new Date());
    } else {
        if (DateHelper.compareDate(login.getMissTime(),new Date())==1){
            return 1;
        }
        //注:此处是获取3个可配参数
        String missNum = enumValueMapper.getValue(Integer.valueOf(FileHelpper.map.get("enumValue.missNum")));//错误登陆限制次数
        String intervalTime = enumValueMapper.getValue(Integer.valueOf(FileHelpper.map.get("enumValue.intervalTime")));//错误登陆间隔(单位:分钟)
        String forbidTime = enumValueMapper.getValue(Integer.valueOf(FileHelpper.map.get("enumValue.forbidTime")));//错误登陆禁止时间(单位:分钟)

        //排除超过禁止时间的错误登陆信息
        List<LoginLog> logs = loginLogMapper.findMissLog(employeeId, login.getMissNumber());
        for (int i = 0; i < logs.size(); i++) {
            LoginLog log = logs.get(i);

            if (DateHelper.getDaysbytwoDate2(new Date(), log.getLoginTime()) > Integer.valueOf(intervalTime)) {
                logs.remove(i);
            }
        }
        login.setMissNumber(logs.size());//设置错误次数

        if (login.getMissNumber() + 1 > Integer.valueOf(missNum)) {//需要禁止登录
            login.setMissFlag("1");
            try {
                login.setMissTime(DateHelper.addDate(new Date(), Long.valueOf(forbidTime)));//加上对应的禁止时间
            } catch (ParseException e) {
                e.printStackTrace();
            }
        } else {
            login.setMissNumber(login.getMissNumber() + 1);
            login.setMissFlag("0");
            login.setMissTime(new Date());
        }
    }
    return loginMissMapper.updateByPrimaryKeySelective(login);
}

/**
 * 判断是否在锁定时间 即:是否可以登录
 */
@Override
public String judgeMiss(Long employeeId) {
    LoginMiss login = loginMissMapper.findLoginByEmployeeId(employeeId);
    if (login == null) {
        addLoginMiss(employeeId, 0);
    }
    if (DateHelper.compareDate(new Date(),login.getMissTime())==1){
        return null;
    }else {//不可以登录
        return DateHelper.dateFormat1(login.getMissTime());
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章