在很多对安全性要求较高的项目中,需要提供至少一种对整个项目的安全控制方案,常用的比如身份认证、访问控制、安全审计等等。由于设计不合理而导致的安全问题可能会给项目带来非常大的隐患,正是因为如此,安全问题也得到了广大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实现相关推荐

  1. java中刷新页面的js,[Java教程]js页面刷新之实现框架内外刷新(整体、局部)

    [Java教程]js页面刷新之实现框架内外刷新(整体.局部) 0 2016-10-12 12:00:56 这次总结的是框架刷新: 框架内外的按钮均可以定义网页重定向, 框架内部页面的按钮可以实现局部刷 ...

  2. 不刷新页面的tab_SwiftUI小技巧之如何解决Tab切换后页面重置和List刷新bug

    SwiftUI的tabview非常好用,简单几行就能构建一套基于Tab的App.但是SwiftUI目前tabview存在一个小bug,当tab切换时内部中的list或NavigationLink将会重 ...

  3. 不刷新页面的tab_现代 Web 页面开发流程

    通常来说,Web页面开发的流程大致是这样的:设计师(设计师不是美工,就像程序员不是码农一样)提供设计稿,通常是图片格式.然后前端的开发人员(在ThoughtWorks我们称之为UI Dev)来手工的将 ...

  4. 婚纱页面的java源代码_基于jsp的婚纱-JavaEE实现婚纱 - java项目源码

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的婚纱, 该项目可用各类java课程设计大作业中, 婚纱的系统架构分为前后台两部分, 最终实现在线上进行婚纱各项功能 ...

  5. C# Asp.net 中的Treeview 点击不刷新页面的

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="huozhu.aspx.cs&q ...

  6. 内网通修改积分文件_转盘抽奖分享得积分,你是如何防止页面被恶意刷新的

    恶意刷新 恶意刷新就是不停的去刷新提交页面,导致出现大量无效数据,这类问题在实际应用中我们经常遇到,比如一个活动的分享得积分,刷票,刷红包等等,遇到这些问题,你是如何去防止的. 当你在做一个刷红包的活 ...

  7. Vue项目中刷新当前页面的四种方法

    Vue项目中刷新当前页面的四种方法 前记 刷新当前页面的四种方法 this.$router.go(0) location.reload() 跳转空白页再跳回原页面 使用provide / inject ...

  8. java刷新当前页面_js刷新当前页面的5种方式

    1. reload reload 方法,该方法强迫浏览器刷新当前页面. 语法:location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 false,从 ...

  9. 页面的div中有滚动条,js实现刷新页面后回到记录时滚动条的位置

    当div中绑定数据,给它一个属性overflow-y: scroll,添加长度大小,使其能够出现滚动条:每次刷新的时候滚动条总是会出现在最上方,这使我很头疼,经过查阅网上资料,返现两种方法可行.如下: ...

最新文章

  1. 『JavaScript』核心
  2. mysql global index_Oracle中addsplit partition对globallocal index的影响
  3. 【nodejs原理源码赏析(3)】欣赏手术级的原型链加工艺术
  4. python制作图片墙_利用python生成照片墙的示例代码
  5. bootstrap日期控件 只显示 年月
  6. 什么是测地线(geodesic)?【讲解清晰生动,深入浅出,通俗易懂】
  7. 精通 C++ 是个毛意思
  8. 软件测试工作中有哪些常用的工具?
  9. mysql远程备份_mysql实现自动远程备份一办法
  10. 网站链接被微信屏蔽禁止访问的解决办法
  11. 小程序拨打电话功能,微信小程序点击手机号,拨打电话~!
  12. 用Java爬虫爬取凤凰财经提供的沪深A股所有股票代号名称
  13. 网站商务BD(Bussiness Development--商务拓展)
  14. 我的秋招经历(已完结)
  15. DI的概念和实现原理—Spring系列介绍
  16. Elasticsearch权限控制
  17. 解决ActiveX组件及Office程序等在Chrome、Edge新内核、360系列、FireFox、IE、Opera等桌面浏览器各版本中的嵌入使用问题
  18. CD34 造血干细胞和造血祖细胞的区别
  19. 原生Array.isArray()判断对象是否为数组
  20. vue更换网页上的标题(Vue-mete)

热门文章

  1. 如何去做词频统计和关键词共现分析
  2. 仿京东或淘宝的订单中心页面
  3. LINUX SHELL宝塔判断域名变化IP脚本
  4. 基于RuoYi框架快速搭建自己的后台管理系统
  5. ios html格式转换,如何使用HTML模版和iOS中的UIPrintPageRenderer来生成PDF文档
  6. lumen5.5 使用 jwt-auth1.0 笔记
  7. SGX初始化中ELF文件解析
  8. RAID 磁盘阵列与阵列卡
  9. 宝塔面板IP域名绑定
  10. 计算机组成原理之计算机最基本的工作原理