2012-07-16 90 views
9

我为我的客户提供Web服务,允许他向生产数据库添加记录。防止多次拨打网络服务

我最近的事件,在我的客户的程序员称为一个循环服务,迭代打电话到我的服务数千​​次。

我的问题是什么才是防止这种事情的最好方法。

我想到了一些方法: 1.在服务入口处,我可以更新每个调用服务的客户端的计数器,但看起来太笨拙。 2.检查调用此服务的客户端的IP,并在每次调用服务时提起一个标志,然后每隔一小时重新设置一次标志。

我敢肯定有更好的方法,并会任何并欣赏的建议。

谢谢,大卫

+0

另一个想法,更新该用户的会话: – 2012-07-16 08:11:59

+0

我相信你有某种“批量“添加方法? – Phil 2012-07-16 08:53:51

+0

是的,有... – 2012-07-16 08:55:30

回答

3

的方法是在会话存储计数器并使用计数器来防止每次太多调用。

但是如果你的用户可能会尽量避免和发送不同的cookie每次*,那么你需要做的是像会话的自定义表,但与IP连接的用户,而不是与cookie。

一个更这里要说的是,如果你的IP模块基本你可能封锁整个公司,出来一个代理。所以最后的正确方法,但更复杂的是有ip和cookie连接用户,并知道浏览器是否允许cookie。如果没有,那么你阻止与IP。这里困难的部分是了解cookie。 在每次通话中,您都可以强制他发送与现有会话相关的有效Cookie。如果没有,那么浏览器没有cookie。

[*] cookies与会话连接。
[*]通过制作新表来保持计数器和会话断开连接,您还可以避免会话锁定。

在过去,我有使用用于DosAttack代码,但他们都不是好工作,当你有多个游泳池和复杂的应用,所以我现在用一个自定义的表,我形容它。这是两个代码,我有测试和使用

Dos attacks in your web app

Block Dos attacks easily on asp.net

如何找到每保存在一个表秒的点击。以下是我计算每秒钟点击次数的SQL部分。其中一个窍门是,如果我从最后一次检查中获得6秒或更多秒,我会继续添加点击并计算平均值。这是从计算剪断作为一种思想

set @cDos_TotalCalls = @cDos_TotalCalls + @NewCallsCounter 

SET @cMilSecDif = ABS(DATEDIFF(millisecond, @FirstDate, @UtpNow)) 

-- I left 6sec diferent to make the calculation 
IF @cMilSecDif > 6000 
    SET @cClickPerSeconds = (@cDos_TotalCalls * 1000/@cMilSecDif) 
else 
    SET @cClickPerSeconds = 0 

IF @cMilSecDif > 30000 
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = @NewCallsCounter, cDos_TotalCallsChecksOn = @UtpNow WHERE [email protected]   
ELSE IF @cMilSecDif > 16000 
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = (cDos_TotalCalls/2), 
    cDos_TotalCallsChecksOn = DATEADD(millisecond, @cMilSecDif/2, cDos_TotalCallsChecksOn) 
     WHERE [email protected] 
+0

感谢您的回答,让我说更新Session:Session [“ServiceInvoked”] = true;并询问我们是否在会议开始时提问:if((bool)Session [“ServiceInvoked”])...我将阻止该呼叫。但是,我怎么会重置它,让我们说,一个小时? – 2012-07-16 08:15:43

+0

如果我将插入日期时间,我可以工作,因为我可以检查会议日期时间Subscract的DateTime.Now,并允许该服务是调用.... – 2012-07-16 08:17:51

+0

@DavidRasuli您一起使用上次更新的日期时间字段与计数器,然后进行平均计算 - 例如,您可以在最后一个DateTime上看到最后一次询问是在1秒之前,并且所有就绪都有10次调用。换句话说,你把它当作最后的电话,而不是现在的电话。 – Aristos 2012-07-16 08:20:05

3

首先,你需要看看你的情况法律方面的代码:是否与你的客户的合同可以限制客户端的访问?

这个问题是出了这么范围的,但是你必须找到一种方式来回答这个问题。因为如果你在法律上有义务处理所有请求,那么就没有办法解决它。此外,对您的情况的法律分析可能已经包含一些限制,您可能会限制访问。这反过来会对您的解决方案产生影响。

抛开所有这些问题,只关注技术方面,您是否使用某种用户认证? (如果没有,为什么不呢?)如果你这样做,你可以实现你决定在每个用户基础上使用的任何方案,我认为这将是最干净的解决方案(你不需要依赖IP地址,这是一个以某种方式丑陋的解决方法)。

一旦你有了识别单个用户的方法,你可以实现多种限制。拳头那些来我的心是这些:

  1. 同步处理
    才开始处理请求所有以前的请求已被受理。这甚至可以用主处理方法中的lock声明来实现。如果你去了这种方法,处理之间
  2. 延时请求
    需要一个处理的呼叫后,使其在下次调用之前的特定时间必须通过。最简单的解决方案是在用户的会话中存储一个LastProcessed时间戳。如果你采用这种方法,你需要开始考虑如何处理新的请求,然后才允许进行处理 - 你是否向调用者发送了错误消息?我想你应该...

编辑
lock声明,简要说明:

其目的是用于线程安全的操作。的语法如下:

lock(lockObject) 
{ 
    // do stuff 
} 

lockObject需要是一个对象,当前类的通常是私有成员。其效果是,如果您有两个线程都想要执行此代码,第一个到达lock语句会锁定lockObject。虽然它是这样的,但第二个线程无法获取锁,因为该对象已被锁定。所以它只是在那里等待,直到第一个线程退出}的块时才释放锁。只有第二个线程可以锁定lockObject并完成它,并阻止lockObject进入第三个线程,直到它退出该块为止。

小心,整个线程安全问题远不是微不足道的。 (人们可以说唯一微不足道的就是程序员可以做出的许多微不足道的错误;-) See here在C#中的线程入门简介

+0

伟大的答案Treb,请你详细说一下关于“锁”的声明,因为我不熟悉它? – 2012-07-16 08:22:00

+1

@David:'lock'在这里有记录http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.100).aspx – Grhm 2012-07-16 08:33:22

0

获取用户ip并在使用web后将其插入缓存一小时服务,这是缓存在服务器:

HttpContext.Current.Cache.Insert("UserIp", true, null,DateTime.Now.AddHours(1),System.Web.Caching.Cache.NoSlidingExpiration); 

当你需要检查用户是否在最后一小时进入:

if(HttpContext.Current.Cache["UserIp"] != null) 
{ 
//means user entered in last hour 
}