<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    憨厚生

    ----Java's Slave----
    ***Java's Host***

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      165 隨筆 :: 17 文章 :: 90 評(píng)論 :: 0 Trackbacks
    轉(zhuǎn) http://blog.csdn.net/zhaowei001/archive/2007/12/29/2001800.aspx

    作者:EasyJF開源團(tuán)隊(duì) 大峽

    一、簡(jiǎn)介

    在Java Web應(yīng)用程中,特別是網(wǎng)站開發(fā)中,我們有時(shí)候需要為應(yīng)用程序增加一個(gè)入侵檢測(cè)程序來(lái)防止惡意刷新的功能,防止非法用戶不斷的往Web應(yīng)用中重復(fù)發(fā)送數(shù) 據(jù)。當(dāng)然,入侵檢測(cè)可以用很多方法實(shí)現(xiàn),包括軟件、硬件防火墻,入侵檢測(cè)的策略也很多。在這里我們主要介紹的是Java Web應(yīng)用程序中通過(guò)軟件的方式實(shí)現(xiàn)簡(jiǎn)單的入侵檢測(cè)及防御。

      該方法的實(shí)現(xiàn)原理很簡(jiǎn)單,就是用戶訪問(wèn)Web系統(tǒng)時(shí)記錄每個(gè)用戶的信息,然后進(jìn)行對(duì)照,并根據(jù)設(shè)定的策略(比如:1秒鐘刷新頁(yè)面10次)判斷用戶是否屬于惡意刷新。

    我們的入侵檢測(cè)程序應(yīng)該放到所有Java Web程序的執(zhí)行前,也即若發(fā)現(xiàn)用戶是惡意刷新就不再繼續(xù)執(zhí)行Java Web中的其它部分內(nèi)容,否則就會(huì)失去了意義。這就需要以插件的方式把入侵檢測(cè)的程序置入Java Web應(yīng)用中,使得每次用戶訪問(wèn)Java Web,都先要到這個(gè)入侵檢測(cè)程序中報(bào)一次到,符合規(guī)則才能放行。

      Java Web應(yīng)用大致分為兩種,一種純JSP(+Java Bean)方式,一種是基于框架(如Struts、EasyJWeb等)的。第一種方式的Java Web可以通過(guò)Java Servlet中的Filter接口實(shí)現(xiàn),也即實(shí)現(xiàn)一個(gè)Filter接口,在其doFilter方法中插入入侵檢測(cè)程序,然后再web.xml中作簡(jiǎn)單的 配置即可。在基于框架的Web應(yīng)用中,由于所有應(yīng)用都有一個(gè)入口,因此可以把入侵檢測(cè)的程序直接插入框架入口引擎中,使框架本身支持入侵檢測(cè)功能。當(dāng)然, 也可以通過(guò)實(shí)現(xiàn)Filter接口來(lái)實(shí)現(xiàn)。

      在EasyJWeb框架中,已經(jīng)置入了簡(jiǎn)單入侵檢測(cè)的程序,因此,這里我們以EasyJWeb框架為例,介紹具體的實(shí)現(xiàn)方法及源碼,完整的代碼可以在EasyJWeb源碼中找到。

      在基于EasyJWeb的Java Web應(yīng)用中(如http://www.easyjf.com/bbs/),默認(rèn)情況下你只要連續(xù)刷新頁(yè)面次數(shù)過(guò)多,即會(huì)彈出如下的錯(cuò)誤:

      EasyJWeb框架友情提示!:-):
      您對(duì)頁(yè)面的刷新太快,請(qǐng)等待60秒后再刷新頁(yè)面!
    詳細(xì)請(qǐng)查詢http://www.easyjf.com


    二、用戶訪問(wèn)信息記錄UserConnect.java類  

    這個(gè)類是一個(gè)簡(jiǎn)單的Java Bean,主要代表用戶的信息,包括用戶名、IP、第一次訪問(wèn)時(shí)間、最后登錄時(shí)間、登錄次數(shù)、用戶狀態(tài)等。全部

    代碼如下:

    package com.easyjf.web;

    import java.util.Date;
    /**
    *
    *

    Title:用戶驗(yàn)證信息


    *

    Description:記錄用戶登錄信息,判斷用戶登錄情況


    *

    Copyright: Copyright (c) 2006


    *

    Company: www.easyjf.com

    >
    * @author 蔡世友
    * @version 1.0
    */
    public class UserConnect {
    private String userName;
    private String ip;
    private Date firstFailureTime;
    private Date lastLoginTime;
    private int failureTimes;//用戶登錄失敗次數(shù)
    private int status=0;//用戶狀態(tài)0表示正常,-1表示鎖定
    public int getFailureTimes() {
     return failureTimes;
    }
    public void setFailureTimes(int failureTimes) {
     this.failureTimes = failureTimes;
    }
    public Date getFirstFailureTime() {
     return firstFailureTime;
    }

    public void setFirstFailureTime(Date firstFailureTime) {
     this.firstFailureTime = firstFailureTime;
    }

    public String getIp() {
     return ip;
    }

    public void setIp(String ip) {
     this.ip = ip;
    }

    public Date getLastLoginTime() {
     return lastLoginTime;
    }

    public void setLastLoginTime(Date lastLoginTime) {
     this.lastLoginTime = lastLoginTime;
    }

    public String getUserName() {
     return userName;
    }

    public void setUserName(String userName) {
     this.userName = userName;
    }

    public int getStatus() {
     return status;
    }

    public void setStatus(int status) {
     this.status = status;
    }

    }


    三、監(jiān)控線程UserConnectManage.java類

    這是入侵檢測(cè)的核心部分,主要實(shí)現(xiàn)具體的入侵檢測(cè)、記錄、判斷用戶信息、在線用戶的刷新等功能,并提供其它應(yīng)用程序使用本組件的調(diào)用接口。

    package com.easyjf.web;

    import java.util.Date;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;

    import org.apache.log4j.Logger;
    /**
    *
    *

    Title:用戶入侵檢測(cè)信息


    *

    Description:用于判斷用戶刷新情況檢查,默認(rèn)為10秒鐘之內(nèi)連續(xù)連接10次為超時(shí)


    *

    Copyright: Copyright (c) 2006


    *

    Company: www.easyjf.com

    >
    * @author 蔡世友
    * @version 1.0
    */
    public class UserConnectManage {
    private static final Logger logger = (Logger) Logger.getLogger(UserConnectManage.class.getName());
    private static int maxFailureTimes=10;//最大登錄失敗次數(shù)
    private static long maxFailureInterval=10000;//毫秒,達(dá)到最大登錄次數(shù)且在這個(gè)時(shí)間范圍內(nèi)
    private static long waitInterval=60000;//失敗后接受連接的等待時(shí)間,默認(rèn)1分鐘
    private static int maxOnlineUser=200;//同時(shí)在線的最大數(shù)
    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) 
     {
      this.parentThread=parentThread; 
      synchronized(this){
      if(checkThread==null){   
       checkThread= new Thread(this);
       //System.out.println("創(chuàng)建一個(gè)新線程!");
       checkThread.start();   
         }
      }
     } 
     public void run() {  
      while(true)
      {
       if(parentThread.isAlive()){
       try{
       Thread.sleep(2000);
       int i=0;
       if(users.size()>maxOnlineUser)//當(dāng)達(dá)到最大用戶數(shù)時(shí)清除
       {
        synchronized(users){//執(zhí)行刪除操作
        Iterator it=users.keySet().iterator();
        Set set=new HashSet();
        Date now=new Date();
        while(it.hasNext())
        {
         Object key=it.next();
         UserConnect user=(UserConnect)users.get(key);
         if(now.getTime()-user.getFirstFailureTime().getTime()>maxFailureInterval)//刪除超時(shí)的用戶
         {      
          set.add(key);
          logger.info("刪除了一個(gè)超時(shí)的連接"+i);
          i++;
         }
        }
        if(i<5)//如果刪除少于5個(gè),則強(qiáng)行刪除1/2在線記錄,犧牲性能的情況下保證內(nèi)存
        {
         int num=maxOnlineUser/2;
         it=users.keySet().iterator();
         while(it.hasNext() && i
         {      
          set.add(it.next());
          logger.info("刪除了一個(gè)多余的連接"+i);
          i++;
         }
        }
        users.keySet().removeAll(set);
        }
       }
       
       }
       catch(Exception e)
       {
        e.printStackTrace();
       }
       
      }
       else
       {   
       break;
       }
      }
      logger.info("監(jiān)視程序運(yùn)行結(jié)束!"); 
     }
    }
    //通過(guò)checkLoginValidate判斷是否合法的登錄連接,如果合法則繼續(xù),非法則執(zhí)行
    public static boolean checkLoginValidate(String ip,String userName)//只檢查認(rèn)證失敗次數(shù)
    {
     boolean ret=true;
     Date now=new Date(); 
     String key=ip+":"+userName;
     UserConnect auth=(UserConnect)users.get(key);
     if(auth==null)//把用戶當(dāng)前的訪問(wèn)信息加入到users容器中
     {
      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)
      {
               //如果在限定的時(shí)間間隔內(nèi),則返回拒絕用戶連接的信息
       if((now.getTime()-auth.getFirstFailureTime().getTime())
       {
        ret=false;
        auth.setStatus(-1);
       }
       else  if(auth.getStatus()==-1 && (now.getTime()-auth.getFirstFailureTime().getTime()< (maxFailureInterval+waitInterval)))//重置計(jì)數(shù)器
       {
        ret=false;
       }
       else    
       {    
        auth.setFailureTimes(0);
        auth.setFirstFailureTime(now);
        auth.setStatus(0);
       }
       
      }
      //登錄次數(shù)加1
      auth.setFailureTimes(auth.getFailureTimes()+1);
     }
     //System.out.println(key+":"+auth.getFailureTimes()+":"+ret+":"+(now.getTime()-auth.getFirstFailureTime().getTime()));
     return ret;
    }

    public static void reset(String ip,String userName)//重置用戶信息

     Date now=new Date(); 
     String key=ip+":"+userName;
     UserConnect auth=(UserConnect)users.get(key);
     if(auth==null)//把用戶當(dāng)前的訪問(wèn)信息加入到users容器中
     {
      auth=new UserConnect();
      auth.setIp(ip);
      auth.setUserName(userName);
      auth.setFailureTimes(0);
      auth.setFirstFailureTime(now);
      users.put(key,auth);
     } 
     else
     {
      auth.setFailureTimes(0);
      auth.setFirstFailureTime(now);
     }
    }
    public static void remove(String ip,String userName)//刪除用戶在容器中的記錄
    {
     String key=ip+":"+userName;
     users.remove(key);
    }
    public static void clear()//清空容器中內(nèi)容
    {
     if(!users.isEmpty())users.clear();
    }
    public static long getMaxFailureInterval() {
     return maxFailureInterval;
    }

    public static void setMaxFailureInterval(long maxFailureInterval) {
     UserConnectManage.maxFailureInterval = maxFailureInterval;
    }

    public static int getMaxFailureTimes() {
     return maxFailureTimes;
    }

    public static void setMaxFailureTimes(int maxFailureTimes) {
     UserConnectManage.maxFailureTimes = maxFailureTimes;
    }

    public static int getMaxOnlineUser() {
     return maxOnlineUser;
    }

    public static void setMaxOnlineUser(int maxOnlineUser) {
     UserConnectManage.maxOnlineUser = maxOnlineUser;
    }

    public static long getWaitInterval() {
     return waitInterval;
    }

    public static void setWaitInterval(long waitInterval) {
     UserConnectManage.waitInterval = waitInterval;
    }


    四、調(diào)用接口

    在需要進(jìn)入侵檢測(cè)判斷的地方,直接使用UserConnectManage類中的checkLoginValidate方法即可。如EasyJWeb的核心Servlet 

    com.easyjf.web.ActionServlet中調(diào)用UserConnectManage的代碼:
       if(!UserConnectManage.checkLoginValidate(request.getRemoteAddr(),"guest"))
           {            
               info(request,response,new Exception("您對(duì)頁(yè)面的刷新太快,請(qǐng)等待"+UserConnectManage.getWaitInterval()/1000+"秒

    后再刷新頁(yè)面!"));
               return;
           }      



    五、總結(jié)
    當(dāng)然,這里提供的方法只是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)示例,由于上面的用戶信息是直接保存在內(nèi)存中,若并發(fā)用戶很大的時(shí)候的代碼的占用,可以考慮引入數(shù)據(jù)庫(kù)來(lái)記錄用 戶的訪問(wèn)信息,當(dāng)然相應(yīng)的執(zhí)行效率肯定用降低。上面介紹的實(shí)現(xiàn)中,入侵檢測(cè)判斷的策略也只有用戶訪問(wèn)次數(shù)及時(shí)間間隔兩個(gè)元素,您還可以根據(jù)你的實(shí)現(xiàn)情況增 加其它的檢測(cè)元素。

    由于水平有限,該設(shè)計(jì)上有N不合理或者需要改進(jìn)的地方,懇請(qǐng)大家指正!



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=657199



    posted on 2009-04-17 16:42 二胡 閱讀(213) 評(píng)論(0)  編輯  收藏 所屬分類: Javaweb系統(tǒng)開發(fā)
    主站蜘蛛池模板: 免费电视剧在线观看| 亚洲 日韩 色 图网站| 国产一级淫片a免费播放口之| 国产精品网站在线观看免费传媒| 亚洲成av人片天堂网无码】| 两个人www免费高清视频| 亚洲中文字幕久久无码| 亚洲精品一卡2卡3卡三卡四卡| 伊人久久精品亚洲午夜| 国产成人免费片在线视频观看| 91情侣在线精品国产免费| 久草免费手机视频| a级毛片免费网站| 午夜亚洲国产理论片二级港台二级| 亚洲成人免费电影| 亚洲成a人片在线观看无码专区| 亚洲福利精品一区二区三区| 日韩在线看片免费人成视频播放| 九九精品免费视频| 国产在线jyzzjyzz免费麻豆| 99精品视频免费在线观看| 三年片在线观看免费| aa级毛片毛片免费观看久| jzzjzz免费观看大片免费| WWW亚洲色大成网络.COM| 亚洲爆乳AAA无码专区| 亚洲AV综合色区无码一二三区 | 免费看内射乌克兰女| 亚洲av无码专区在线观看下载| 国产精品亚洲片在线va| 亚洲综合国产成人丁香五月激情 | 一区二区三区在线免费观看视频| 免费手机在线看片| 午夜亚洲乱码伦小说区69堂| 最新亚洲人成无码网www电影| 美女隐私免费视频看| 九九久久精品国产免费看小说| 黄色免费在线网址| 一级做a爱片特黄在线观看免费看| 一道本不卡免费视频| 中文字幕免费人成乱码中国|