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) {} /** * * @Title:doAround * @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()); } }