繁体   English   中英

防止多次调用Web服务

[英]Prevent calling a web service too many times

我为我的客户提供Web服务,允许他将记录添加到生产数据库。

我最近遇到了一个事件,我的客户程序员在一个循环中调用该服务,迭代调用我的服务数千​​次。

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

我想到了一些方法:1。对服务的参与,我可以为每个调用该服务的客户更新计数器,但这看起来太过于笨拙。 2.检查呼叫此服务的客户端的IP,并在每次呼叫服务时提出标志,然后每小时重置一次标志。

我很肯定有更好的方法,并会提出任何建议。

谢谢,大卫

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

但是,如果您的用户可能会尝试避免这种情况并且每次都发送不同的cookie *,那么您需要创建一个类似于会话的自定义表,但是将用户与ip连接,而不是与cookie连接。

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

[*] Cookie与会话相关联。
[*]通过使新表保持计数器并与会话断开连接,您还可以避免会话锁定。

在过去,我使用了一个用于DosAttack的代码,但是当你有许多池和困难的应用程序时,它们都不能正常工作,所以我现在使用自定义表来描述它。 这是我测试和使用的两个代码

您的网络应用中的Dos攻击

在asp.net上轻松阻止Dos攻击

如何查找保存在表格上的每秒点击次数。 以下是我计算每秒点击次数的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 cLiveUsersID=@cLiveUsersID         
ELSE IF @cMilSecDif > 16000
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = (cDos_TotalCalls / 2), 
    cDos_TotalCallsChecksOn = DATEADD(millisecond, @cMilSecDif / 2, cDos_TotalCallsChecksOn)
        WHERE cLiveUsersID=@cLiveUsersID

首先,您需要了解您的情况的法律方面: 与您的客户签订的合同是否允许您限制客户的访问权限?

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

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

一旦您确定了识别单个用户的方法,就可以实施多项限制。 我想到的第一个是这些:

  1. 同步处理
    仅在处理完所有先前的请求后才开始处理请求。 除了主处理方法中的lock语句之外,甚至可以实现这一点。 如果你采取这种方法,
  2. 处理请求之间的时间延迟
    要求在一次处理呼叫后,必须在允许下一次呼叫之前通过特定时间。 最简单的解决方案是在用户的会话中存储LastProcessed时间戳。 如果你采用这种方法,你需要开始考虑如何在允许处理新请求之前响应 - 你是否向调用者发送错误消息? 我想你应该...

编辑
lock声明,简要解释:

它旨在用于线程安全操作。 语法如下:

lock(lockObject)
{
    // do stuff
}

lockObject需要是一个对象,通常是当前类的私有成员。 结果是如果你有2个线程都想要执行这个代码,那么第一个到达lock语句的lockObject锁定lockObject 虽然它确实是这样,但第二个线程无法获取锁定,因为该对象已被锁定。 所以它只是坐在那里,等待直到第一个线程释放锁时,它退出块在} 只有第二个线程可以锁定lockObject并执行它的操作,阻止任何第三个线程的lockObject ,直到它也退出块。

小心,整个线程安全问题远非微不足道。 (可以说,唯一可以解决的问题是程序员可以做出的许多琐碎错误;-) 请参阅此处了解C#中的线程故障

获取用户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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM