正常的用户每天的登录退出不会太频繁,遇到频繁的登录则很可能是黑客行为。对于黑客行为,我们可以使用登录次数限制来应对。本文将介绍如何限制用户每天的登录次数,包括:“记录当天用户账号的登录次数”、“用户进行登录请求时,检查当天账号的登录次数”、“用户正常退出登录,更新登录次数”。
1、记录当天用户账号的登录次数。
定义hashmap类型的属性mapLoginCountIn1Day,用来存储当前用户账号(key)和登录账号的次数(value):
protected static Map<String, Object> mapLoginCountIn1Day = new HashMap<String, Object>();
定义另一个hashmap类型的属性mapLoginDay,用户存储当前日期(key)和mapLoginCountIn1Day(value):
protected static Map<String, Object> mapLoginDay = new HashMap<String, Object>();
2、用户进行登录请求时,检查当天账号的登录次数。
在checkLoginCount方法检查登录次数:
@SuppressWarnings("unchecked")
protected boolean checkLoginCount(Object phone, ErrorInfo ecOut) {
boolean bLoginToManyTimes = false; // 检查Staff是否登录次数过多
lock.writeLock().lock();
try {
BxConfigGeneral cgMaxRequestCountIn1Day = (BxConfigGeneral) CacheManager.getCache(BaseAction.DBName_Public, EnumCacheType.ECT_BXConfigGeneral).read1(BaseCache.MaxLoginCountIn1Day, BaseBO.SYSTEM, ecOut, BaseAction.DBName_Public);
int MAX_LoginCountIn1Day = Integer.valueOf(cgMaxRequestCountIn1Day.getValue());
// MAX_LoginCountIn1Day = 5;
String dateForDay = sdfLoginCountIn1Day.format(new Date());
if (mapLoginDay.get(dateForDay) == null) {
mapLoginDay.clear();
mapLoginCountIn1Day.put(String.valueOf(phone), 1);
mapLoginDay.put(dateForDay, mapLoginCountIn1Day);
} else {
mapLoginCountIn1Day = (Map<String, Object>) mapLoginDay.get(dateForDay);
if (mapLoginCountIn1Day.get(phone) == null) {
mapLoginCountIn1Day.put(String.valueOf(phone), 1);
} else {
int currentLoginCountIn1Day = (int) mapLoginCountIn1Day.get(phone);
mapLoginCountIn1Day.put(String.valueOf(phone), ++currentLoginCountIn1Day);
if (currentLoginCountIn1Day >= MAX_LoginCountIn1Day) {
if (currentLoginCountIn1Day % MAX_LoginCountIn1Day == 0) {
logger.error("手机号码" + phone + "当天已超过登录次数,已登录" + currentLoginCountIn1Day + "次");
}
bLoginToManyTimes = true;
}
}
}
} catch (Exception e) {
logger.error(e.getMessage());
}
lock.writeLock().unlock();
//
if (bLoginToManyTimes) {
return false;// 从此禁止用户再次登录。那么,用户什么时候可以再次登录?1、重启Tomcat。2、给OP开发一个接口。(后面再做)
}
return true;
}
首先判断在当前日期有没有用户登录过mapLoginDay.get(dateForDay),没有登录过则清空mapLoginDay,并将该账号的登录次数设为1,缓存到mapLoginDay。
如果当前日期有用户登录过:
判断当前用户有无登录过,没有登录过将该账号的登录次数设为1,缓存到mapLoginDay。登录过就将账号的登录次数加1。如果登录次数大于设定的值MAX_LoginCountIn1Day(可以在数据库定义、读取),就阻止用户在当天的登录。
3、用户正常退出登录,更新登录次数。
用户退出登录请求接口:
@RequestMapping(value = "/logoutEx", produces = "plain/text; charset=UTF-8", method = RequestMethod.GET)
@ResponseBody
public String logout(HttpSession session) {
if (!canCallCurrentAction(session, BaseAction.EnumUserScope.STAFF.getIndex())) {
logger.debug("无权访问本Action");
return null;
}
Company company = getCompanyFromSession(session);
Staff staff = (Staff) session.getAttribute(EnumSession.SESSION_Staff.getName()); // ...定义常量
logger.info("服务器的登出,staff=" + staff);
Map<String, Object> params = new HashMap<String, Object>();
if (staff != null) {
// 更新Staff登录次数
updateLoginCount(staff.getPhone());
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());
Pos pos = (Pos) session.getAttribute(EnumSession.SESSION_POS.getName());
if (pos != null && pos.getID() != BaseAction.INVALID_POS_ID) {
sendLogoutMsgToWx(staff, company);
}
// if (staff.getInt3() == 1 || Staff.DEFINE_GET_RoleID(staff.getInt1()) == 1) {
// sendMsgToWx(staff, company);
// }
} else {
logger.info("其他错误");
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());
}
params.put(KEY_HTMLTable_Parameter_msg, staffBO.getLastErrorMessage());
logger.info("返回的数据=" + params);
EnumSession.clearAllSession(session);
session.invalidate();
return JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();
}
updateLoginCount方法更新登录次数:
@SuppressWarnings("unchecked")
protected void updateLoginCount(Object phone) {
lock.writeLock().lock();
//
try {
String dateForDay = sdfLoginCountIn1Day.format(new Date());
if (mapLoginDay.get(dateForDay) != null) {
mapLoginCountIn1Day = (Map<String, Object>) mapLoginDay.get(dateForDay);
if (mapLoginCountIn1Day.get(phone) != null) {
int currentLoginCountIn1Day = (int) mapLoginCountIn1Day.get(phone);
mapLoginCountIn1Day.put(String.valueOf(phone), --currentLoginCountIn1Day);
}
}
} catch (Exception e) {
logger.error(e.getMessage());
}
//
lock.writeLock().unlock();
}