在 Java Web 應用開發中,特別是公開網站,常面臨惡意刷新、暴力破解、資料重複提交等攻擊。入侵偵測系統(IDS)能即時識別異常存取模式,保護系統資源不被濫用。雖然有硬體/軟體防火牆方案,但在應用層實作輕量級偵測邏輯,能更精準針對業務場景防禦。
實作邏輯直觀:記錄每位用戶的存取資訊(IP、用戶名、時間、頻率),根據預設策略(如:10 秒內連續請求超過 10 次)判定是否為惡意行為。偵測程式必須置於所有 Web 請求處理之前——若判定為惡意,直接攔截並回應錯誤,否則放行繼續執行。
javax.servlet.Filter 介面,在 doFilter() 中植入偵測邏輯,於 web.xml 設定攔截路徑EasyJWeb 框架內建簡易入侵偵測,預設觸發時回應:
您對頁面的刷新太快,請等待60秒後再刷新頁面!
記錄單一用戶的狀態資訊:
package com.easyjf.web;
import java.util.Date;
public class UserConnect {
private String userName;
private String ip;
private Date firstFailureTime; // 首次失敗時間
private Date lastLoginTime; // 最後登入時間
private int failureTimes; // 失敗/請求次數
private int status = 0; // 0=正常, -1=鎖定
// Getter/Setter 方法...
}
核心偵測邏輯,採用單例模式管理所有用戶連線資訊,內含定期清理的監控執行緒:
package com.easyjf.web;
import java.util.*;
import org.apache.log4j.Logger;
public class UserConnectManage {
private static final Logger logger = Logger.getLogger(UserConnectManage.class.getName());
// 設定參數
private static int maxFailureTimes = 10; // 最大允許失敗次數
private static long maxFailureInterval = 10000; // 時間窗口(毫秒):10秒
private static long waitInterval = 60000; // 鎖定等待時間:60秒
private static int maxOnlineUser = 200; // 最大同時在線用戶
// 用戶資訊容器:key = "ip:username"
private final static Map users = new HashMap();
private static Thread checkThread = null;
// 內部類別:定期清理逾時/過期連線記錄
private static class CheckTimeOut implements Runnable {
private Thread parentThread;
public CheckTimeOut(Thread parentThread) {
this.parentThread = parentThread;
synchronized(this) {
if (checkThread == null) {
checkThread = new Thread(this);
checkThread.start();
}
}
}
public void run() {
while (true) {
if (parentThread.isAlive()) {
try {
Thread.sleep(2000); // 每2秒檢查一次
// 1. 移除超時記錄
// 2. 若在線用戶超過上限,強制清理舊記錄保護記憶體
// 詳細邏輯見原始碼...
} catch (Exception e) {
e.printStackTrace();
}
} else break;
}
logger.info("監視程式結束!");
}
}
// 核心驗證方法:判斷請求是否合法
public static boolean checkLoginValidate(String ip, String userName) {
boolean ret = true;
Date now = new Date();
String key = ip + ":" + userName;
UserConnect auth = (UserConnect) users.get(key);
if (auth == null) {
// 首次請求,建立記錄
auth = new UserConnect();
auth.setIp(ip);
auth.setUserName(userName);
auth.setFailureTimes(0);
auth.setFirstFailureTime(now);
users.put(key, auth);
if (checkThread == null) new CheckTimeOut(Thread.currentThread());
} else {
// 檢查是否超過頻率限制
if (auth.getFailureTimes() > maxFailureTimes) {
if ((now.getTime() - auth.getFirstFailureTime().getTime()) < maxFailureInterval) {
ret = false; // 在時間窗內超頻,拒絕
auth.setStatus(-1);
} else if (auth.getStatus() == -1 &&
(now.getTime() - auth.getFirstFailureTime().getTime()) < (maxFailureInterval + waitInterval)) {
ret = false; // 鎖定期內,持續拒絕
} else {
// 時間窗已過,重置計數器
auth.setFailureTimes(0);
auth.setFirstFailureTime(now);
auth.setStatus(0);
}
}
// 請求計數 +1
auth.setFailureTimes(auth.getFailureTimes() + 1);
}
return ret;
}
// 重置用戶狀態(如登入成功後)
public static void reset(String ip, String userName) {
// 實作細節...
}
}
應用層入侵偵測是 Web 安全防禦的重要一環。EasyJWeb 的實作展示了輕量級、可嵌入、可配置的偵測架構。實務上可根據業務風險等級,結合 WAF、行為分析、機器學習等進階手段,構建多層次防禦體系。