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

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

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

    隨筆 - 115  文章 - 481  trackbacks - 0
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(19)

    隨筆檔案(115)

    文章檔案(4)

    新聞檔案(1)

    成員連接

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

          作者:EasyJF開源團隊 大峽

    一、簡介

      在Java Web應用程中,特別是網站開發中,我們有時候需要為應用程序增加一個入侵檢測程序來防止惡意刷新的功能,防止非法用戶不斷的往Web應用中重復發送數據。當然,入侵檢測可以用很多方法實現,包括軟件、硬件防火墻,入侵檢測的策略也很多。在這里我們主要介紹的是Java Web應用程序中通過軟件的方式實現簡單的入侵檢測及防御。

      該方法的實現原理很簡單,就是用戶訪問Web系統時記錄每個用戶的信息,然后進行對照,并根據設定的策略(比如:1秒鐘刷新頁面10次)判斷用戶是否屬于惡意刷新。

      我們的入侵檢測程序應該放到所有Java Web程序的執行前,也即若發現用戶是惡意刷新就不再繼續執行Java Web中的其它部分內容,否則就會失去了意義。這就需要以插件的方式把入侵檢測的程序置入Java Web應用中,使得每次用戶訪問Java Web,都先要到這個入侵檢測程序中報一次到,符合規則才能放行。

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

      在EasyJWeb框架中,已經置入了簡單入侵檢測的程序,因此,這里我們以EasyJWeb框架為例,介紹具體的實現方法及源碼,完整的代碼可以在EasyJWeb源碼中找到。

      在基于EasyJWeb的Java Web應用中(如http://www.easyjf.com/bbs/),默認情況下你只要連續刷新頁面次數過多,即會彈出如下的錯誤:

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


    二、用戶訪問信息記錄UserConnect.java類  

      這個類是一個簡單的Java Bean,主要代表用戶的信息,包括用戶名、IP、第一次訪問時間、最后登錄時間、登錄次數、用戶狀態等。全部

    代碼如下:

    package com.easyjf.web;

    import java.util.Date;
    /**
    *
    * <p>Title:用戶驗證信息</p>
    * <p>Description:記錄用戶登錄信息,判斷用戶登錄情況</p>
    * <p>Copyright: Copyright (c) 2006</p>
    * <p>Company: www.easyjf.com</p>
    * @author 蔡世友
    * @version 1.0
    */
    public class UserConnect {
    private String userName;
    private String ip;
    private Date firstFailureTime;
    private Date lastLoginTime;
    private int failureTimes;//用戶登錄失敗次數
    private int status=0;//用戶狀態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;
    }

    }


    三、監控線程UserConnectManage.java類

      這是入侵檢測的核心部分,主要實現具體的入侵檢測、記錄、判斷用戶信息、在線用戶的刷新等功能,并提供其它應用程序使用本組件的調用接口。

    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;
    /**
    *
    * <p>Title:用戶入侵檢測信息</p>
    * <p>Description:用于判斷用戶刷新情況檢查,默認為10秒鐘之內連續連接10次為超時</p>
    * <p>Copyright: Copyright (c) 2006</p>
    * <p>Company: www.easyjf.com</p>
    * @author 蔡世友
    * @version 1.0
    */
    public class UserConnectManage {
    private static final Logger logger = (Logger) Logger.getLogger(UserConnectManage.class.getName());
    private static int maxFailureTimes=10;//最大登錄失敗次數
    private static long maxFailureInterval=10000;//毫秒,達到最大登錄次數且在這個時間范圍內
    private static long waitInterval=60000;//失敗后接受連接的等待時間,默認1分鐘
    private static int maxOnlineUser=200;//同時在線的最大數
    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("創建一個新線程!");
    ???checkThread.start();???
    ???? }
    ??}
    ?}?
    ?public void run() {??
    ??while(true)
    ??{
    ???if(parentThread.isAlive()){
    ???try{
    ???Thread.sleep(2000);
    ???int i=0;
    ???if(users.size()>maxOnlineUser)//當達到最大用戶數時清除
    ???{
    ????synchronized(users){//執行刪除操作
    ????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)//刪除超時的用戶
    ?????{??????
    ??????set.add(key);
    ??????logger.info("刪除了一個超時的連接"+i);
    ??????i++;
    ?????}
    ????}
    ????if(i<5)//如果刪除少于5個,則強行刪除1/2在線記錄,犧牲性能的情況下保證內存
    ????{
    ?????int num=maxOnlineUser/2;
    ?????it=users.keySet().iterator();
    ?????while(it.hasNext() && i<num)
    ?????{??????
    ??????set.add(it.next());
    ??????logger.info("刪除了一個多余的連接"+i);
    ??????i++;
    ?????}
    ????}
    ????users.keySet().removeAll(set);
    ????}
    ???}
    ???
    ???}
    ???catch(Exception e)
    ???{
    ????e.printStackTrace();
    ???}
    ???
    ??}
    ???else
    ???{???
    ???break;
    ???}
    ??}
    ??logger.info("監視程序運行結束!");?
    ?}
    }
    //通過checkLoginValidate判斷是否合法的登錄連接,如果合法則繼續,非法則執行
    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)//把用戶當前的訪問信息加入到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)
    ??{
    ?????????? //如果在限定的時間間隔內,則返回拒絕用戶連接的信息
    ???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);
    ?}
    ?//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)//把用戶當前的訪問信息加入到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()//清空容器中內容
    {
    ?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;
    }


    四、調用接口

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

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

    后再刷新頁面!"));
    ? ? ? ? ? ?return;
    ? ? ? ?}??????

      
        
    五、總結
      當然,這里提供的方法只是一個簡單的實現示例,由于上面的用戶信息是直接保存在內存中,若并發用戶很大的時候的代碼的占用,可以考慮引入數據庫來記錄用戶的訪問信息,當然相應的執行效率肯定用降低。上面介紹的實現中,入侵檢測判斷的策略也只有用戶訪問次數及時間間隔兩個元素,您還可以根據你的實現情況增加其它的檢測元素。

      由于水平有限,該設計上有N不合理或者需要改進的地方,懇請大家指正!

    posted on 2006-04-11 10:05 簡易java框架 閱讀(1679) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲国产无套无码av电影| 亚洲精品国产va在线观看蜜芽| 亚洲AV成人一区二区三区AV| 国产免费牲交视频免费播放 | 免费观看国产小粉嫩喷水| 亚洲黄页网在线观看| 色se01短视频永久免费| ASS亚洲熟妇毛茸茸PICS| 成年女人免费视频播放体验区| 亚洲国产综合精品中文第一| 国内外成人免费视频| 国产成人亚洲精品电影| 又色又污又黄无遮挡的免费视| 日日狠狠久久偷偷色综合免费| 中文字幕亚洲天堂| 一区二区三区无码视频免费福利| 亚洲色欲色欲综合网站| xxxx日本免费| 精品无码专区亚洲| 中文字幕精品亚洲无线码二区| 特级做A爰片毛片免费看无码| 久久亚洲AV无码精品色午夜 | 免费大片黄在线观看yw| 亚洲熟女综合一区二区三区| 国产美女做a免费视频软件| 日韩精品无码免费视频| 亚洲AV美女一区二区三区| 四虎永久在线观看免费网站网址 | 国产成人精品免费视频软件| 一级成人a免费视频| 亚洲AV本道一区二区三区四区| 成人免费无遮挡无码黄漫视频| 免费看又黄又爽又猛的视频软件 | 亚洲色中文字幕在线播放| 国产亚洲日韩一区二区三区| 69影院毛片免费观看视频在线 | baoyu777永久免费视频| 精品久久亚洲中文无码| 亚洲日韩在线观看| 99爱在线精品免费观看| 一级女人18片毛片免费视频|