正常的用戶每天的登錄退出不會太頻繁,遇到頻繁的登錄則很可能是黑客行為。對於黑客行為,我們可以使用登錄次數限制來應對。本文將介紹如何限制用戶每天的登錄次數,包括:“記錄當天用戶賬號的登錄次數”、“用戶進行登錄請求時,檢查當天賬號的登錄次數”、“用戶正常退出登錄,更新登錄次數”。
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();
}