熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

在Java Web中的入侵檢測及實現

2013-11-23 19:36:07  來源: Java核心技術 

  一簡介
   
    在Java Web應用程中特別是網站開發中我們有時候需要為應用程序增加一個入侵檢測程序來防止惡意刷新的功能防止非法用戶不斷的往Web應用中重復發送數據當然入侵檢測可以用很多方法實現包括軟件硬件防火牆入侵檢測的策略也很多在這裡我們主要介紹的是Java Web應用程序中通過軟件的方式實現簡單的入侵檢測及防御
   
    該方法的實現原理很簡單就是用戶訪問Web系統時記錄每個用戶的信息然後進行對照並根據設定的策略(比如秒鐘刷新頁面次)判斷用戶是否屬於惡意刷新
   
    我們的入侵檢測程序應該放到所有Java Web程序的執行前也即若發現用戶是惡意刷新就不再繼續執行Java Web中的其它部分內容否則就會失去了意義這就需要以插件的方式把入侵檢測的程序置入Java Web應用中使得每次用戶訪問Java Web都先要到這個入侵檢測程序中報一次到符合規則才能放行
   
    Java Web應用大致分為兩種一種純JSP(+Java Bean)方式一種是基於框架(如StrutsEasyJWeb等)的第一種方式的Java Web可以通過Java Servlet中的Filter接口實現也即實現一個Filter接口在其doFilter方法中插入入侵檢測程序然後再webxml中作簡單的配置即可在基於框架的Web應用中由於所有應用都有一個入口因此可以把入侵檢測的程序直接插入框架入口引擎中使框架本身支持入侵檢測功能當然也可以通過實現Filter接口來實現
   
    在EasyJWeb框架中已經置入了簡單入侵檢測的程序因此這裡我們以EasyJWeb框架為例介紹具體的實現方法及源碼完整的代碼可以在EasyJWeb源碼中找到
   
    在基於EasyJWeb的Java Web應用中默認情況下你只要連續刷新頁面次數過多即會彈出如下的錯誤
   
    EasyJWeb框架友情提示!
   
    您對頁面的刷新太快請等待秒後再刷新頁面!
   
    二用戶訪問信息記錄UserConnectjava類
   
    這個類是一個簡單的Java Bean主要代表用戶的信息包括用戶名IP第一次訪問時間最後登錄時間登錄次數用戶狀態等全部
   
    代碼如下
   
    package comeasyjfweb;
   
    import javautilDate;
   
    /**
   
    *
   
    *
   
    Title:用戶驗證信息
   
    *
   
    Description:記錄用戶登錄信息判斷用戶登錄情況
   
    *
   
    Copyright: Copyright (c)
   
    *
   
    Company:
   
    * @author 蔡世友
   
    * @version
   
    */
   
    public class UserConnect {
   
    private String userName;
   
    private String ip;
   
    private Date firstFailureTime;
   
    private Date lastLoginTime;
   
    private int failureTimes;//用戶登錄失敗次數
   
    private int status=;//用戶狀態表示正常表示鎖定
   
    public int getFailureTimes() {
   
    return failureTimes;
   
    }
   
    public void setFailureTimes(int failureTimes) {
   
    thisfailureTimes = failureTimes;
   
    }
   
    public Date getFirstFailureTime() {
   
    return firstFailureTime;
   
    }
   
    public void setFirstFailureTime(Date firstFailureTime) {
   
    thisfirstFailureTime = firstFailureTime;
   
    }
   
    public String getIp() {
   
    return ip;
   
    }
   
    public void setIp(String ip) {
   
    thisip = ip;
   
    }
   
    public Date getLastLoginTime() {
   
    return lastLoginTime;
   
    }
   
    public void setLastLoginTime(Date lastLoginTime) {
   
    thislastLoginTime = lastLoginTime;
   
    }
   
    public String getUserName() {
   
    return userName;
   
    }
   
    public void setUserName(String userName) {
   
    thisuserName = userName;
   
    }
   
    public int getStatus() {
   
    return status;
   
    }
   
    public void setStatus(int status) {
   
    thisstatus = status;
   
    }
   
    }
   
    三監控線程UserConnectManagejava類
   
    這是入侵檢測的核心部分主要實現具體的入侵檢測記錄判斷用戶信息在線用戶的刷新等功能並提供其它應用程序使用本組件的調用接口
   
    package comeasyjfweb;
   
    import javautilDate;
   
    import javautilHashMap;
   
    import javautilHashSet;
   
    import javautilIterator;
   
    import javautilMap;
   
    import javautilSet;
   
    import orgapachelogjLogger;
   
    /**
   
    *
   
    *
   
    Title:用戶入侵檢測信息
   
    *
   
    Description:用於判斷用戶刷新情況檢查默認為秒鐘之內連續連接次為超時
   
    *
   
    Copyright: Copyright (c)
   
    *
   
    Company:
   
    * @author 蔡世友
   
    * @version
   
    */
   
    public class UserConnectManage {
   
    private static final Logger logger = (Logger) LoggergetLogger(UserConnectManageclassgetName())
   
    private static int maxFailureTimes=;//最大登錄失敗次數
   
    private static long maxFailureInterval=;//毫秒達到最大登錄次數且在這個時間范圍內
   
    private static long waitInterval=;//失敗後接受連接的等待時間默認分鐘
   
    private static int maxOnlineUser=;//同時在線的最大數
   
    private final static Map users=new HashMap()//使用ip+userName為key存放用戶登錄信息UserLoginAuth
   
    private static Thread checkThread=null;
   
    private static class CheckTimeOut implements Runnable{
   
    private Thread parentThread;
   
    public CheckTimeOut(Thread parentThread)
   
    {
   
    thisparentThread=parentThread;
   
    synchronized(this){
   
    if(checkThread==null){
   
    checkThread= new Thread(this)
   
    //Systemoutprintln(創建一個新線程!
   
    checkThreadstart()
   
    }
   
    }
   
    }
   
    public void run() {
   
    while(true)
   
    {
   
    if(parentThreadisAlive()){
   
    try{
   
    Threadsleep(
   
    int i=;
   
    if(userssize()>maxOnlineUser)//當達到最大用戶數時清除
   
    {
   
    synchronized(users){//執行刪除操作
   
    Iterator it=userskeySet()iterator()
   
    Set set=new HashSet()
   
    Date now=new Date()
   
    while(ithasNext())
   
    {
   
    Object key=itnext()
   
    UserConnect user=(UserConnect)usersget(key)
   
    if(nowgetTime()usergetFirstFailureTime()getTime()>maxFailureInterval)//刪除超時的用戶
   
    {
   
    setadd(key)
   
    (刪除了一個超時的連接+i)


   
    i++;
   
    }
   
    }
   
    if(i<)//如果刪除少於則強行刪除/在線記錄犧牲性能的情況下保證內存
   
    {
   
    int num=maxOnlineUser/;
   
    it=userskeySet()iterator()
   
    while(ithasNext() && i {
   
    setadd(itnext())
   
    (刪除了一個多余的連接+i)
   
    i++;
   
    }
   
    }
   
    userskeySet()removeAll(set)
   
    }
   
    }
   
    }
   
    catch(Exception e)
   
    {
   
    eprintStackTrace()
   
    }
   
    }
   
    else
   
    {
   
    break;
   
    }
   
    }
   
    (監視程序運行結束!
   
    }
   
    }
   
    //通過checkLoginValidate判斷是否合法的登錄連接如果合法則繼續非法則執行
   
    public static boolean checkLoginValidate(String ipString userName)//只檢查認證失敗次數
   
    {
   
    boolean ret=true;
   
    Date now=new Date()
   
    String key=ip+:+userName;
   
    UserConnect auth=(UserConnect)usersget(key)
   
    if(auth==null)//把用戶當前的訪問信息加入到users容器中
   
    {
   
    auth=new UserConnect()
   
    authsetIp(ip)
   
    authsetUserName(userName)
   
    authsetFailureTimes(
   
    authsetFirstFailureTime(now)
   
    usersput(keyauth)
   
    if(checkThread==null)new CheckTimeOut(ThreadcurrentThread())
   
    }
   
    else
   
    {
   
    if(authgetFailureTimes()>maxFailureTimes)
   
    {
   
    //如果在限定的時間間隔內則返回拒絕用戶連接的信息
   
    if((nowgetTime()authgetFirstFailureTime()getTime()) {
   
    ret=false;
   
    authsetStatus(
   
    }
   
    else if(authgetStatus()== && (nowgetTime()authgetFirstFailureTime()getTime()<(maxFailureInterval+waitInterval)))//重置計數器
   
    {
   
    ret=false;
   
    }
   
    else
   
    {
   
    authsetFailureTimes(
   
    authsetFirstFailureTime(now)
   
    authsetStatus(
   
    }
   
    }
   
    //登錄次數加
   
    authsetFailureTimes(authgetFailureTimes()+
   
    }
   
    //Systemoutprintln(key+:+authgetFailureTimes()+:+ret+:+(nowgetTime()authgetFirstFailureTime()getTime()))
   
    return ret;
   
    }
   
    public static void reset(String ipString userName)//重置用戶信息
   
    {
   
    Date now=new Date()
   
    String key=ip+:+userName;
   
    UserConnect auth=(UserConnect)usersget(key)
   
    if(auth==null)//把用戶當前的訪問信息加入到users容器中
   
    {
   
    auth=new UserConnect()
   
    authsetIp(ip)
   
    authsetUserName(userName)
   
    authsetFailureTimes(
   
    authsetFirstFailureTime(now)
   
    usersput(keyauth)
   
    }
   
    else
   
    {
   
    authsetFailureTimes(
   
    authsetFirstFailureTime(now)
   
    }
   
    }
   
    public static void remove(String ipString userName)//刪除用戶在容器中的記錄
   
    {
   
    String key=ip+:+userName;
   
    usersremove(key)
   
    }
   
    public static void clear()//清空容器中內容
   
    {
   
    if(!usersisEmpty())usersclear()
   
    }
   
    public static long getMaxFailureInterval() {
   
    return maxFailureInterval;
   
    }
   
    public static void setMaxFailureInterval(long maxFailureInterval) {
   
    UserConnectManagemaxFailureInterval = maxFailureInterval;
   
    }
   
    public static int getMaxFailureTimes() {
   
    return maxFailureTimes;
   
    }
   
    public static void setMaxFailureTimes(int maxFailureTimes) {
   
    UserConnectManagemaxFailureTimes = maxFailureTimes;
   
    }
   
    public static int getMaxOnlineUser() {
   
    return maxOnlineUser;
   
    }
   
    public static void setMaxOnlineUser(int maxOnlineUser) {
   
    UserConnectManagemaxOnlineUser = maxOnlineUser;
   
    }
   
    public static long getWaitInterval() {
   
    return waitInterval;
   
    }
   
    public static void setWaitInterval(long waitInterval) {
   
    UserConnectManagewaitInterval = waitInterval;
   
    }
   
    四調用接口
   
    在需要進入侵檢測判斷的地方直接使用UserConnectManage類中的checkLoginValidate方法即可如EasyJWeb的核心Servlet
   
    comeasyjfwebActionServlet中調用UserConnectManage的代碼
   
    if(!UserConnectManagecheckLoginValidate(requestgetRemoteAddr()guest))
   
    {
   
    info(requestresponsenew Exception(您對頁面的刷新太快請等待+UserConnectManagegetWaitInterval()/+
   
    後再刷新頁面!))
   
    return;
   
    }
   
    五總結
   
    當然這裡提供的方法只是一個簡單的實現示例由於上面的用戶信息是直接保存在內存中若並發用戶很大的時候的代碼的占用可以考慮引入數據庫來記錄用戶的訪問信息當然相應的執行效率肯定用降低上面介紹的實現中入侵檢測判斷的策略也只有用戶訪問次數及時間間隔兩個元素您還可以根據你的實現情況增加其它的檢測元素


From:http://tw.wingwit.com/Article/program/Java/hx/201311/27150.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.