`
jamesby
  • 浏览: 383439 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

如何防止用户恶意的F5刷新操作的问题?

    博客分类:
  • Java
阅读更多
背景:
  问题是这样的,系统持久层采用ibatis架构,系统有几个比较复杂的报表,耗费时间稍微长,不过在3秒以内.
   但是在报表页面按 F5 10秒钟则会出现statement timeout 的异常,因此有了如何防止用户恶意刷新的想法.

初步想法
   在内存中维护一个类似集合的东西,记录url,userid和访问时间,该集合的数据量维护在一个合理的范围,采用先进先出原则,根据访问时间、url和userid判断用户访问某个url的频繁程度,利用Interceptor从而在用户访问service之前拒绝用户访问!

   谁能提供一个更好的想法?    


分享到:
评论
12 楼 jamesby 2007-02-26  
抛出异常的爱 写道
你的测试如何写啊?(现在比较关心这种特例的测试写法)
这个没有考虑过,哪位给点经验?
11 楼 抛出异常的爱 2007-02-26  
你的测试如何写啊?(现在比较关心这种特例的测试写法)
10 楼 jamesby 2007-02-26  
目前的代码如下:

public class UserVisiteRecord {
	private int _interval = 3000;

	private String url = "-1";

	private long time = 0;

	public UserVisiteRecord(String url) {
		init(url);
	}

	private void init(String url) {
		//synchorized(user) 如何?
		this.url = url;
		time = new Date().getTime();
	}

	public boolean isValidateVisite(String currentUrl) {
		long currenttime = new Date().getTime();
		if (currentUrl.equals(url) && currenttime - time < _interval) {
			return false;
		}
		init(currentUrl);
		return true;
	}

	public void release() {
		this.url = "-1";
	}
}


public class SecurityInterceptor extends HandlerInterceptorAdapter {
	protected final Log log = LogFactory.getLog(SecurityInterceptor.class);

	private final Map _cache = new HashMap();

	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler, ModelAndView mv)
			throws Exception {
		User user = (User) WebUtils.getSessionAttribute(request, "user");
		if (null != user) {
			Integer userid = user.getLinkmanid();
			UserVisiteRecord uvr = (UserVisiteRecord) _cache.get(userid);
			if (null != uvr) {
				uvr.release();
			}
		}
	}

	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		User user = (User) WebUtils.getSessionAttribute(request, "user");
		if (user == null) {
			ModelAndView modelAndView = new ModelAndView(new RedirectView(
					"/cm/login.do"));

			throw new ModelAndViewDefiningException(modelAndView);
		} else {
			Integer userid = user.getLinkmanid();
			UserVisiteRecord uvr = (UserVisiteRecord) _cache.get(userid);
			String url = request.getRequestURL().toString();
			if (null == uvr) {
				_cache.put(userid, new UserVisiteRecord(url));
			} else {
				if (!uvr.isValidateVisite(url)) {
					ModelAndView error = new ModelAndView("error");
					throw new ModelAndViewDefiningException(error);
				}
			}
			return true;
		}
	}
9 楼 抛出异常的爱 2007-02-26  
jamesby 写道
如果采用Interceptor拦截,pre设置标志,post释放标志,不更合理,而且是可插拔式的!

你用的方式比我的偶合小
不过我的方法是我用过了的。。。(一年之前系统中没有spring,我也没有spring的思考方式。)

放cache主要是为了再刷时不用再去作大表查寻了。。。
(存在内存中的不止一组查寻结果集。。。。)

BufferString是String的父类当有变化时时减少资源浪费
(如果是String那么url+"/xxx.do?"+"zzz=yyy"+"&aaa=bbb"+"&cccc=dddd")
8 楼 jamesby 2007-02-26  
如果采用Interceptor拦截,pre设置标志,post释放标志,不更合理,而且是可插拔式的!
7 楼 jamesby 2007-02-26  
lordhong 写道
jamesby 写道

1放一个cache放到这个方法中有没有用?
把报表数据cache一下?不大好,因为毕竟报表数据要时实的。

为什么不好? 数据更新了就invalidate cache.  除非你的数据是每时每刻都在更新, 那么在user session里面放个refresh buffer delay, 比如5秒内的重复请求一律无视
我一个报表涉及到10几个表左右,这样的cache似乎不妥.invalidate率太高.

抛出异常的爱的方法很可行.

6 楼 lordhong 2007-02-25  
jamesby 写道

1放一个cache放到这个方法中有没有用?
把报表数据cache一下?不大好,因为毕竟报表数据要时实的。

为什么不好? 数据更新了就invalidate cache.  除非你的数据是每时每刻都在更新, 那么在user session里面放个refresh buffer delay, 比如5秒内的重复请求一律无视
5 楼 jamesby 2007-02-25  
说到synchronized突然产生了一个想法,controller的代码写成如下这样大家看如何?

public ModuleAndView handleReport(....)
{
    synchronized(session.getAttribute("user"))
    {
        //产生报表
    }
}
4 楼 jamesby 2007-02-25  
恩,这种方法合理,也比较科学,对于同一个用户来说相当于使用synchronized了!

目前打算对几个复杂的耗时长的报表用楼上的方法,然后加我的拦截方法对所有URL拦截.

另外发现一个新的疑惑,为什么request.getRequestURL()的返回值被设计成StringBuffer而不是String?

这个问题无关紧要,纯粹是专牛角。
3 楼 抛出异常的爱 2007-02-25  
是要在每个报表前加
标置
结束时把标置变成0

可以重构成一个盒子用方法调用
不要次次都写
2 楼 jamesby 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次则认为是恶意的。
不知道这样是否有问题?

1 楼 抛出异常的爱 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");


相关推荐

    防止恶意刷新

    // 阻止F5刷新、Ctrl+R刷新 if ((event.keyCode == 116) || (event.ctrlKey && event.keyCode == 82)) { event.keyCode = 0; event.returnValue = false; } } ()"&gt; ``` 此外,代码还包含了其他一些扩展功能...

    禁止浏览器刷新和鼠标刷新还有键盘刷新

    需要注意的是,过于限制用户的操作可能会影响用户体验,并且可能会被恶意用户利用。例如,禁用F5刷新可能导致用户在页面加载错误时无法刷新页面。此外,浏览器的安全策略可能会阻止某些禁用行为,尤其是涉及用户...

    刷新是不可能刷新的这辈子不可能刷新的

    但问题在于,当用户尝试通过JavaScript禁用或改变这个行为时,浏览器通常会出于安全考虑不允许这样做,因为这可能被恶意代码利用。 在JavaScript中,我们不能完全阻止用户按下F5键或使用浏览器菜单进行刷新,但我们...

    javascript经典特效---禁止刷新页面.rar

    在JavaScript编程中,有时我们可能需要实现特定的功能,比如防止用户意外或恶意地刷新页面,以确保数据的一致性和用户体验。这个"javascript经典特效---禁止刷新页面.rar"压缩包文件包含了一个示例,展示了如何使用...

    多功能网页刷新助手 (1).zip

    通常,用户可以通过浏览器上的刷新按钮或按下键盘上的F5键来实现这一操作。然而,对于需要频繁刷新的网页,手动操作无疑会增加用户的负担,这就是网页刷新工具应运而生的原因。 "多功能网页刷新助手"正如其名,提供...

    VBS语言如:wshshell.sendkeys "{F5}" 'F5按钮

    这对于自动化某些需要频繁按F5刷新的场景非常有用。 3. **VBS语法与注释**: 在VBS中,单行注释以单引号 `'` 开始。例如,`'F5按钮` 是对代码作用的简单注释,告诉读者这段代码的作用是按下F5键。 4. **应用实例*...

    一种Java Web数据提交中的防刷新令牌.pdf

    用户正常的操作处理并没有问题,但是用户可能无意或有意通过反复刷新页面(例如按 F5 键),导致数据的重复提交。甚至,通过代码的自动刷新方式,恶意反复提交数据。这很容易导致数据的混乱或不一致,并极大地增加...

    网页快速刷新浏览工具

    网页快速刷新浏览工具是一款专为用户设计的高效浏览软件,主要功能在于提供快速刷新网页的能力,尤其适用于需要频繁刷新页面的场景,如抢购、报名等。这款工具由作者自行编写,强调其无病毒特性,确保了用户在使用...

    解决win7资源管理器不自动刷新

    然而,有时可能会遇到资源管理器不自动刷新的问题,这可能导致用户无法立即看到文件或文件夹的更新,比如新建、删除、重命名等操作后,变化不会实时反映在窗口中。这种问题可能会影响工作效率,因此解决这个问题至关...

    ASP.Net中防止刷新自动触发事件的解决方案

    例如,恶意用户可能绕过客户端脚本,直接通过其他方式刷新页面。因此,建议在服务器端添加额外的安全检查机制。 - **用户体验**:对于非技术人员来说,这种做法可能会显得有些奇怪。可以考虑在页面中添加提示信息,...

    屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键 的javascript代码

    3. **安全性**:虽然这些代码可以防止一些简单的操作,但对于高级用户或恶意攻击者来说,这些措施往往不够有效。 #### 六、总结 本文详细介绍了如何通过JavaScript代码实现屏蔽鼠标右键、Ctrl+n、Shift+F10、F5...

    IE被恶意修改的十三种简单处理办法.docx

    1. 手动修改注册表:进入`HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer`分支,新建`ControlPanel`主键,在其中新建一个DWORD值,命名为`HomePage`,值设为`00000000`,然后按F5刷新。 2. 自动导入注册表...

    js 特效 html 特效 禁止刷新页面

    这个需求在一些数据交互频繁或者游戏应用中尤为常见,防止用户意外或恶意地刷新导致数据丢失或游戏进程被重置。本篇将详细介绍如何使用JavaScript(JS)和HTML特效来实现禁止页面刷新的功能。 首先,我们要理解的是...

    网络程序设计课程-课下作业_乱写1

    2. 防止重复提交和刷新:在网络应用程序中,尤其是在涉及数据修改的操作中,防止用户意外或恶意重复提交是一个重要的问题。例如,多次点击提交按钮可能导致数据的不一致。解决这个问题的一种常见方法是在服务器端...

    JSP防止网页刷新重复提交数据的几种方法

    在网页开发中,尤其是涉及到数据提交的场景,防止用户意外或恶意重复提交是非常重要的,因为这可能导致数据不一致和系统异常。JSP(JavaServer Pages)作为动态网页技术,提供了多种方式来解决这个问题。以下是一些...

    网页保护方法大全.pdf

    在脚本中,通过`onKeyDown()`函数检测特定按键的按下事件,例如`event.keyCode==116`(F5刷新)、`window.event.ctrlKey`(Ctrl键)、`window.event.shiftKey`以及`event.keyCode==122`(F2键),并且让这些操作无效...

    IE恶意网页破坏的简单修复方法.

    ### IE恶意网页破坏的简单修复方法 #### 一、默认主页被修改 **破坏特性**: 默认主页被自动更改为某个特定网站...通过以上步骤,可以有效地解决IE浏览器遭遇恶意网页破坏时的各种问题,确保用户的上网体验安全可靠。

    IE被恶意修改的十三种简单处理法.docx

    当IE浏览器遭遇恶意修改时,用户通常会发现主页、默认搜索引擎等被篡改,甚至无法通过常规设置恢复。以下介绍十三种简单处理办法来解决这一问题。 1. **默认主页被修改** - **处理方法**:通过手动修改注册表来...

    php防止用户重复提交表单

    在用户操作中,重复提交表单可能是因为用户无意中多次点击了提交按钮,或是攻击者故意尝试多次提交表单以达到某种恶意目的,比如耗尽服务端资源。 对于防止用户重复提交表单,可以采取多种方法: 1. 前端限制。...

Global site tag (gtag.js) - Google Analytics