1. 程式人生 > >防止惡意重新整理頁面的Java實現

防止惡意重新整理頁面的Java實現

在很多對安全性要求較高的專案中,需要提供至少一種對整個專案的安全控制方案,常用的比如身份認證、訪問控制、安全審計等等。由於設計不合理而導致的安全問題可能會給專案帶來非常大的隱患,正是因為如此,安全問題也得到了廣大web專案開發者的重視,尤其是在電子政務和電子商務的開發中,更是需要提供一定層次上的安全性要求。
本文的重點在於實現一種防止惡意重新整理頁面的方法,筆者在實現該功能時,查找了很多資料並且進行了多次討論協商,提出了這種針對特定需求的,獨立性較高的方案。

    下面,我們來具體說一下客戶的需求。
     該功能是在某電子政務的安全審計子系統中要求實現的一個功能,因為安全審計子系統涉及多方面的內容,包括外網訪問日誌,專網和內網辦公日誌,

資料庫操作日誌等等的控制和查詢等等,通過這些功能,可以提供給管理員各種介面,從而可以檢視系統的使用狀況,並對誤操作或者惡意操作進行有效追蹤和審計。而外網作為電子政務的門戶,是為廣大公眾提供訪問的介面,那麼保證其正常瀏覽是作為電子政務系統中不可或缺的功能需求,因此,實現防止惡意重新整理的功能便是提供良好功能保障的眾多手段中的一種。

    這裡所說的惡意重新整理並不是指網路上通常所指的如何通過javascript指令碼來遮蔽F5鍵等方案,而是通過過濾機制,由程式實現的一種對某次會話中的惡意訪問的控制,該方案中制定的規則是:來自某一客戶的訪問如果在10秒中內超過10次則被假設為惡意訪問。這樣的方案也是比較合理的,既避免了惡意使用者使用F5鍵來頻繁重新整理某一固定頁面,也防止了使用者漫無目的地亂點頁面。同時,該方案還提供了輔助功能,在規則設定方面比較靈活,預設為10次/10秒,這兩個引數是可以通過程式來設定的;在惡意控制方面,如果使用者的訪問違反了該規則,則通過過濾器機制提取該使用者的IP地址,將其置為拒絕提供服務的IP列表中,將拒絕再次為來自該IP的請求提供服務。
    下面,我們來具體說明一下該方案的實現方法。
    首先,從整個方案的實施體系來講,我們提取出如下的控制流程。

從上圖可以看出,來自客戶端的請求首先要經過IP過濾器的過濾,只有不在惡意IP列表中的IP地址的請求才有可能被響應,然後還要經過惡意重新整理過濾器的驗證才能得到伺服器的最終響應。如果該IP在10秒內連續請求的次數達到了10次,那麼,它將被記入到惡意IP列表中,將不會通過IP過濾器的驗證,不會得到伺服器的響應,從而,我們就實現了對惡意使用者的過濾。當然,通過IP過濾器的作用,我們還可以將某些IP直接列入黑名單中,比如某些具有攻擊性的網站的IP地址或者曾經通過網路入侵檢測軟體的診斷,將危險IP也加入黑名單,這樣,可以提高我們的應用的安全性和可用性。

    接下來,我們通過程式碼來看一下如何具體實現我們的功能。通過上面的流程圖,我們可以清晰看到,在應用中,我們配置了兩個過濾器(關於過濾器的原理和實現,請讀者參考相關資料),當然,我們也可以將其寫在一個過濾器的doFilter()方法中。
本文方案的實現中採用了兩個過濾器,下面我們來簡單看一下IP過濾器。以下是具體的程式碼實現,通過程式碼中的註釋,可以清楚看到我們的實現思路。

從上圖可以看出,來自客戶端的請求首先要經過IP過濾器的過濾,只有不在惡意IP列表中的IP地址的請求才有可能被響應,然後還要經過惡意重新整理過濾器的驗證才能得到伺服器的最終響應。如果該IP在10秒內連續請求的次數達到了10次,那麼,它將被記入到惡意IP列表中,將不會通過IP過濾器的驗證,不會得到伺服器的響應,從而,我們就實現了對惡意使用者的過濾。當然,通過IP過濾器的作用,我們還可以將某些IP直接列入黑名單中,比如某些具有攻擊性的網站的IP地址或者曾經通過網路入侵檢測軟體的診斷,將危險IP也加入黑名單,這樣,可以提高我們的應用的安全性和可用性。

    接下來,我們通過程式碼來看一下如何具體實現我們的功能。通過上面的流程圖,我們可以清晰看到,在應用中,我們配置了兩個過濾器(關於過濾器的原理和實現,請讀者參考相關資料),當然,我們也可以將其寫在一個過濾器的doFilter()方法中。
本文方案的實現中採用了兩個過濾器,下面我們來簡單看一下IP過濾器。以下是具體的程式碼實現,通過程式碼中的註釋,可以清楚看到我們的實現思路。

HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; String ip = request.getRemoteAddr(); //得到客戶端IP地址 if(!req.getRequestURI().toUpperCase().equals("ERR.JSP")) ...{ IP ipControl = new IP(); //生成一個IP類的事例 try ...{ // getDangerousIP(ip)將查詢指定IP是否在IP黑名單的資料庫中 if((ip != null )&&(ipControl.getDangerousIP(ip) !=0)) ...{ res.sendRedirect("/err.jsp?errmsg=ip"); } else ...{ //如果該IP安全,則繼續執行 chain.doFilter(request, response); } } catch (ServletException ex) ...{ ex.printStackTrace(); } catch (IOException ex) ...{ ex.printStackTrace(); } catch (Exception ex) ...{ ex.printStackTrace(); } finally...{ ipControl.closeConn();//關閉資料庫連線 } 下面,我們來著重討論如何實現惡意重新整理的過濾器。因為我們的需求是在任何的10秒中記錄請求數而不是在以10秒為一個時間段,那麼就需要保證時間的連續性,鑑於此需求,我們需要儲存使用者連續10次請求的時間,如果其最後一次的請求時間與第一次的時間差小於10秒並且次數已經達到10次,則違背設定規則,我們設計了下面的類來儲存使用者的訪問時間序列。

public class ArrayTime ...{ private long[] time; private int length = 10; //預設為十次(10s內重新整理10次則違反規則) public ArrayTime() ...{ } public void init() ...{ time = new long[length]; } public int getLength() ...{ return this.length; } public void setLength(int len) ...{ this.length = len; } public long getLast() ...{ return this.time[length-1]; } public long getFirst() ...{ return this.time[0]; } public long getElement(int i) ...{ return time[i]; } public void insert(long nextTime) ...{ if (this.getLast() != 0)//陣列已經滿了 ...{ //去掉首元素,將陣列元素順序前移,nextTime插到最後 for(int i = 0 ;i < this.length-1;i++) ...{ time[i] = time[i+1]; } this.time[length-1] = nextTime; } else ...{ //插到下一個,不用排序 int j=0; while(time[j] != 0) ...{ j++; } time[j] = nextTime; } } }  這裡要注意的是,因為我們為管理員提供了規則設定的介面,所以儲存時間序列的陣列長度是可設定的。下面是來自客戶端的訪問者類的實現:
public class Visitor ...{ /**//* Creates a new instance of Visitor *外網訪問者,以sessionID作為標識 *違反訪問規則將其IP列為受限IP,拒絕訪問 */ private String sessionID = null; private ArrayTime requestTimeQueue= new ArrayTime(); public Visitor() ...{ } public void setSessionID(String sessionID) ...{ this.sessionID = sessionID; } public String getSessionID() ...{ return this.sessionID; } public void setRequestTimeQueue(ArrayTime requestTimeQueue) ...{ this.requestTimeQueue = requestTimeQueue; } public ArrayTime getRequestTimeQueue() ...{ return this.requestTimeQueue; } }     該類中採用了訪問者的會話ID來標識來自客戶端的請求,讀者可以很方便地修改該標識,比如修改為註冊會員的使用者名稱,這樣,就可以實現對會員的惡意訪問的遮蔽,同時這樣的好處還在於,可以屏棄對session和cookies的依賴,因為如果使用者瀏覽器如果禁用cookie,通常利用session和cookies實現的惡意重新整理就失去了作用。雖然,我們這樣做也可能是一種消耗記憶體的方式,但是,的確是一種值得采用並進行優化的折中方案。
最後,也是最關鍵的就是我們如何來通過過濾器實現對惡意使用者的請求進行遮蔽。下面是該過濾器的doFliter()方法的核心部分的實現。
//---------------防止惡意重新整理的過濾器-------- HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; String sessionID = ((HttpServletRequest)request).getSession().getId();//會話ID Date now =new Date(); Visitor vis = (Visitor) visitors.get(sessionID);//通過sessionID查詢訪問者, if(vis!= null)//找到訪問者,則說明該使用者為再次訪問 ...{ //小於10秒,但訪問超過10次 vis.getRequestTimeQueue().insert(now.getTime());//插入當前請求時間 //得到最後一次和第一次的訪問時間差 Long span = vis.getRequestTimeQueue().getLast() - vis.getRequestTimeQueue().getFirst(); if(span < interval && vis.getRequestTimeQueue().getLast() != 0) ...{ //將該使用者加入黑名單 IP ip = new IP(); ip.setIP(request.getRemoteAddr()); //得到當前時間 Calendar cal = Calendar.getInstance(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time=formatter.format(cal.getTime()); ip.setComments("重新整理太快,IP已經被封鎖"); try ...{ ip.insertIP(); res.sendRedirect("err.jsp?errmsg=refresh"); return; }catch(Exception e) ...{ e.printStackTrace(); }finally...{ ip.closeConn();} } } else ...{ //當前訪問者為初次訪問 ArrayTime timeQueue = new ArrayTime(); timeQueue.setLength(maxCount); timeQueue.init(); vis=new Visitor(); vis.setSessionID(sessionID); vis.setRequestTimeQueue(timeQueue); vis.getRequestTimeQueue().insert(now.getTime()); visitors.put(sessionID,vis); }     本文中的實現方案為管理員提供了靈活的介面,可以根據實際需要設定相應規則,重新整理過濾器中的兩個引數都是可設定的,比如:
//以下兩個值可從檔案或資料庫設定,從而達到引數的可設定 private static long interval= GlobalConfig.getInt("refresh.interval",10000); //預設10秒鐘 private static int maxCount = GlobalConfig.getInt("refresh.count",10);//預設最大訪問次數    該方案的實現中採用了儲存時間序列的方案,而這樣,就要在記憶體中開闢一個可變可控的陣列,在一定程度上浪費了資源,但是,也提供了在保證連續時間下防止惡意重新整理的功能,並且可以屏棄對session和cookies的依賴,達到完全的可自控,保證了有效性。同時,提供了IP過濾機制來保證功能體系的完善和有效,目前該方案在專案中應用良好。如果讀者對此有更加適合的解

相關推薦

防止惡意重新整理頁面的Java實現

在很多對安全性要求較高的專案中,需要提供至少一種對整個專案的安全控制方案,常用的比如身份認證、訪問控制、安全審計等等。由於設計不合理而導致的安全問題可能會給專案帶來非常大的隱患,正是因為如此,安全問題也得到了廣大web專案開發者的重視,尤其是在電子政務和電子商務的開發中,

自動重新整理頁面實現方法總結

1) <meta   http-equiv= "refresh "content= "10;url=跳轉的頁面 "> 10表示間隔10秒重新整理一次 2) <script   language= ' 'javascript ' '> wind

php防止惡意重新整理與刷票的方法

<?phpsession_start();?><html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>通過session禁止頁面重新

vue專案中上拉載入和下拉重新整理頁面實現

功能:上拉載入,下拉重新整理使用方法:1. 自己建立一個.vue的檔案(我自己是建立了一個PullToRefresh.vue的檔案),將程式碼貼上進去,具體的樣式問題自己在該檔案中調整。<template lang="html"> <div class=

JAVA實現註冊頁面驗證碼重新整理

撰寫人——軟體二班——陳喜平 需要的工具:tomcat/eclipse/jdk/(注意jdk版本要和tomca相匹配,以及注意區分32位和64位) 步驟:依次建立servlet (伺服器需要)/ jsp(頁面需要) 引入web.xml 如圖所示: doget方法裡面的程式碼: prot

java實現將excle資料匯入到web頁面

1.Service實現類 @Override public List<ListExcle> loadScoreInfo(String xlsPath) throws IOException { List<ListExcle> temp =

BJUI接受TabID實現新增或編輯後自動重新整理頁面

場景 藉助於BJUI框架,不管是新增還是編輯,都要共用同一個頁面,執行同一個save方法。 參照: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/84098171 但是實現新增或者編輯後不會自動重新整理頁面,還要我

java實現刪除某條資訊並重新整理當前頁

//執行的是刪除資訊的操作 String a=request.getParameter("name"); a = URLEncoder.encode(a, "ISO-8859-1"); String name

作業系統- 實驗四 模擬FIFO頁面置換演算法(Java實現

                                          &

使用dropdownlist能實現重新整理頁面的效果具體例子

至少VS2008 sp1 以上 <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> //ASP.NET中使用UpdatePanel實現區域性非同步重新整

Ajax如何實現從前端不重新整理頁面就可以到後端取到資料

        提到axaj很多人總說很難,什麼回撥函式呀等等就讓人心煩,其實懂得ajax在js裡面是如何實現向伺服器請求資料的原理,那麼理解ajax也就不是很難了,現在我們一起來看看。          ajax作用:ajax技術的目的是讓javascript傳送http請求,與後臺通訊,獲取資料和資訊。實

微信小程式 返回上一頁面實現上一頁面重新整理

假如從頁面B返回頁面A時實現頁面A重新整理 頁面B: var pages = getCurrentPages();//當前頁面棧 if (pages.length > 1) { var beforePage = pages[pages.length - 2];/

請求頁式儲存管理中頁面置換演算法的java實現

        儲存管理的主要功能之一是合理地分配空間。請求頁式管理是一種常用的虛擬儲存管理技術。         模擬頁式虛擬儲存管理中硬體的地址轉換和缺頁中斷,並用先進先出排程演算法(FIFO)處理缺頁中斷。 &nb

禁止滑鼠點右鍵 - 防止重新整理頁面 - 禁止複製 chrome 和 firefox不能複製

document.oncontextmenu = function () {//點右鍵,啥反應都沒有了   return false; } document.onkeydown = function () { // ctrl+c 也沒有用了,只對ie有效。firefox和chrom

Ajax請求返回一個頁面實現頁面區域性重新整理

本文實現Ajax的區域性重新整理。思路如下: 首先,從JSP頁面A.jsp向服務端發起一個Ajax請求,由Action中方法MethodA處理,該MethodA方法進行資料組裝後,返回一個jsp頁面Result.jsp,然後在Ajax的返回結果中,將Result.jsp元素

Django中用Jquery實現重新整理頁面進行身份驗證和計算器功能

1.下載jquery http://www.jq22.com/jquery-info122 下載解壓之後加入工程中的static資料夾中 2.路由分發。 """Django_demo1 URL Configuration The `urlpatterns` list routes URLs

js實現重新整理頁面後回到記錄時滾動條的位置

區域性重新整理後,要求滾動條在原下拉時的位置: 1、將頁面的div的scrolltop距離長度記錄在cookie中,然後通過js調整重新整理頁面時的長度記錄,程式碼如下 <div id="x" style="height: 200px; overflow

java實現動態驗證碼原始碼——jsp頁面

    我們通常在其他網站註冊或者登陸的時候會發現一個很高大上的驗證碼,那麼怎麼用java程式碼實現呢?下面我給大家貼一下我寫的方法:    此文章是寫的前臺jsp頁面的程式碼: <%@ page language="java" import="java.util.*

防止重新整理頁面造成表單重複提交

  public partial class _Default : System.Web.UI.Page {     protected void Page_Load(object sender, EventArgs e)     {         //第一次載入的時候,

用錨點anchor和location.reload 實現點選重新整理頁面並同時跳轉到本頁面指定位置

群裡看到“如何實現點選重新整理頁面並同時跳轉到本頁面指定位置”這麼一個提問,於是抽空寫了個demo,做了個簡單實現,供大家參考。這裡有2個要求: 1)要重新整理頁面 2)跳轉到頁面指定位置 如果我們簡單用a標籤name屬性,錨點(anchor)來處理的話,只能實現跳轉到頁面指定位置,而不能重