锁定老帖子 主题:如何防止用户恶意的F5刷新操作的问题?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-02-25
问题是这样的,系统持久层采用ibatis架构,系统有几个比较复杂的报表,耗费时间稍微长,不过在3秒以内. 但是在报表页面按 F5 10秒钟则会出现statement timeout 的异常,因此有了如何防止用户恶意刷新的想法. 初步想法 在内存中维护一个类似集合的东西,记录url,userid和访问时间,该集合的数据量维护在一个合理的范围,采用先进先出原则,根据访问时间、url和userid判断用户访问某个url的频繁程度,利用Interceptor从而在用户访问service之前拒绝用户访问! 谁能提供一个更好的想法? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-02-25
1放一个cache放到这个方法中有没有用?
2在application中放一个存userid的map 当一个service运行时 同一个id只能跳过逻辑代码 Map userMap = applictaion.getAtrriblet("userMap"); if userMap==null{ appliction.setAtrriblet("userMap",new HashTable()); }else if userMap.get(userid)==null{ userMap.add(userid,new Integer(9); }else if userMap.get(userid).equles(new Integer(9)){ return getforward("islock"); }else { //return getforword("");//内存中有可以试试用缓存数据 } //TODO 报表 //ok userMap.set(userid,new Integer(0)); return getforward("ok"); |
|
返回顶楼 | |
发表时间:2007-02-25
抛出异常的爱 写道 1放一个cache放到这个方法中有没有用?
2在application中放一个存userid的map 当一个service运行时 同一个id只能跳过逻辑代码 Map userMap = applictaion.getAtrriblet("userMap"); if userMap==null{ appliction.setAtrriblet("userMap",new HashTable()); }else if userMap.get(userid)==null{ userMap.add(userid,new Integer(9); }else if userMap.get(userid).equles(new Integer(9)){ return getforward("islock"); }else { //return getforword("");//内存中有可以试试用缓存数据 } //TODO 报表 //ok userMap.set(userid,new Integer(0)); return getforward("ok"); 1放一个cache放到这个方法中有没有用? 把报表数据cache一下?不大好,因为毕竟报表数据要时实的。 对于第二种,不是很理解,应该有个时间的概念在里面吧。 下面是我的简单的代码实现,我用Spring MVC因此采用Interceptor拦截。 Interceptor 代码 public class SignonInterceptor extends HandlerInterceptorAdapter { Map _CACHE = new HashMap(); public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Integer userid = new Integer(1); //真实的Userid String url = request.getRequestURL().toString(); UserVisitRecord uvr = (UserVisitRecord) _CACHE.get(userid); if (uvr == null) { _CACHE.put(userid, new UserVisitRecord(url)); } else { if (!uvr.isValidateVisite(url)) { //lock redirect to error page } } return true; } } UserVisitRecord 代码 public class UserVisitRecord { private static final int _interval = 1000;//1秒钟 private String url; private long time1 = 0;// early private long time2 = 0;// late public UserVisitRecord(String url) { this.url = url; } private void init(String url) { this.url = url; this.time1 = 0; this.time2 = 0; } private void sequence(long currenttime) { time2 = time1; time1 = currenttime; } private boolean isValidateInterval(long currenttime) { if (currenttime - time2 > _interval) return true; return false; } public boolean isValidateVisite(String currenturl) { long currenttime = new Date().getTime(); if (!currenturl.equals(url)) { init(currenturl); return true; } if (!isValidateInterval(currenttime)) { init(currenturl); return false; } sequence(currenttime); return true; } } 原理是如果同一个用户在一秒钟内连续三次访问同一个URL超过3次则认为是恶意的。 不知道这样是否有问题? |
|
返回顶楼 | |
发表时间:2007-02-25
是要在每个报表前加
标置 结束时把标置变成0 可以重构成一个盒子用方法调用 不要次次都写 |
|
返回顶楼 | |
发表时间:2007-02-25
恩,这种方法合理,也比较科学,对于同一个用户来说相当于使用synchronized了!
目前打算对几个复杂的耗时长的报表用楼上的方法,然后加我的拦截方法对所有URL拦截. 另外发现一个新的疑惑,为什么request.getRequestURL()的返回值被设计成StringBuffer而不是String? 这个问题无关紧要,纯粹是专牛角。 |
|
返回顶楼 | |
发表时间:2007-02-25
说到synchronized突然产生了一个想法,controller的代码写成如下这样大家看如何?
public ModuleAndView handleReport(....) { synchronized(session.getAttribute("user")) { //产生报表 } } |
|
返回顶楼 | |
发表时间:2007-02-25
jamesby 写道 1放一个cache放到这个方法中有没有用? 把报表数据cache一下?不大好,因为毕竟报表数据要时实的。 为什么不好? 数据更新了就invalidate cache. 除非你的数据是每时每刻都在更新, 那么在user session里面放个refresh buffer delay, 比如5秒内的重复请求一律无视 |
|
返回顶楼 | |
发表时间:2007-02-26
lordhong 写道 jamesby 写道 1放一个cache放到这个方法中有没有用? 把报表数据cache一下?不大好,因为毕竟报表数据要时实的。 为什么不好? 数据更新了就invalidate cache. 除非你的数据是每时每刻都在更新, 那么在user session里面放个refresh buffer delay, 比如5秒内的重复请求一律无视 抛出异常的爱的方法很可行. |
|
返回顶楼 | |
发表时间:2007-02-26
如果采用Interceptor拦截,pre设置标志,post释放标志,不更合理,而且是可插拔式的!
|
|
返回顶楼 | |
发表时间:2007-02-26
jamesby 写道 如果采用Interceptor拦截,pre设置标志,post释放标志,不更合理,而且是可插拔式的!
你用的方式比我的偶合小 不过我的方法是我用过了的。。。(一年之前系统中没有spring,我也没有spring的思考方式。) 放cache主要是为了再刷时不用再去作大表查寻了。。。 (存在内存中的不止一组查寻结果集。。。。) BufferString是String的父类当有变化时时减少资源浪费 (如果是String那么url+"/xxx.do?"+"zzz=yyy"+"&aaa=bbb"+"&cccc=dddd") |
|
返回顶楼 | |