Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止多次调用web服务_C#_Asp.net_Web Services - Fatal编程技术网

C# 防止多次调用web服务

C# 防止多次调用web服务,c#,asp.net,web-services,C#,Asp.net,Web Services,我为我的客户提供了一个Web服务,允许他向生产数据库添加记录 我最近发生了一件事,在这件事中,我的客户的程序员在一个循环中调用服务,迭代调用我的服务数千次 我的问题是,防止这种事情发生的最好办法是什么 我想了一些办法: 1.在进入该服务时,我可以为调用该服务的每个客户端更新计数器,但这看起来太笨拙了。 2.检查调用此服务的客户端的IP,并在每次调用该服务时升起一个标志,然后每小时重置标志 我肯定有更好的方法,并会听取任何建议 谢谢,David,方法是在会话中存储一个计数器,并使用计数器防止每次呼

我为我的客户提供了一个Web服务,允许他向生产数据库添加记录

我最近发生了一件事,在这件事中,我的客户的程序员在一个循环中调用服务,迭代调用我的服务数千次

我的问题是,防止这种事情发生的最好办法是什么

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

我肯定有更好的方法,并会听取任何建议


谢谢,David,方法是在会话中存储一个计数器,并使用计数器防止每次呼叫过多

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

这里还有一个问题,如果你在ip上屏蔽basic,你可能会屏蔽来自代理的整个公司。因此,最后一种正确但更复杂的方法是让ip和cookie都与用户连接,并知道浏览器是否允许cookie。如果不是,则使用ip阻止。这里最困难的部分是了解饼干在每次通话中,您都可以强制他发送与现有会话连接的有效cookie。如果没有,则浏览器没有cookie

[*]Cookie与会话连接。
[*]通过创建新表来保留计数器并断开与会话的连接,还可以避免会话锁定

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

如何查找表上保存的每秒点击次数。下面是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地址,这是一个丑陋的解决办法)

一旦有了识别单个用户的方法,就可以实现几个限制。我首先想到的是:

  • 同步处理
    仅在处理完之前的所有请求后才开始处理请求。这甚至可以在主处理方法中只使用
    lock
    语句来实现。如果你采用这种方法
  • 处理请求之间的时间延迟
    要求在一次处理呼叫后,必须经过一段特定时间才能允许下一次呼叫。最简单的解决方案是在用户会话中存储
    LastProcessed
    时间戳。如果您采用这种方法,您需要开始考虑在允许处理新请求之前,当新请求传入时如何响应—您是否向调用者发送错误消息?我想你应该
  • 编辑
    lock
    语句,简要说明:

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

    lock(lockObject)
    {
        // do stuff
    }
    
    lockObject
    需要是一个对象,通常是当前类的私有成员。其效果是,如果有两个线程都希望执行此代码,那么第一个到达
    lock
    语句的线程将锁定
    lockObject
    。当它执行它的任务时,第二个线程无法获得锁,因为对象已经被锁定。因此,它只是坐在那里等待,直到第一个线程在
    }
    退出块时释放锁。只有当第二个线程可以锁定
    lockObject
    并执行它的操作时,才能为任何第三个线程阻塞
    lockObject
    ,直到它也退出块

    小心,整个线程安全性问题绝不是微不足道的。(可以说,它唯一微不足道的地方就是程序员可能犯的许多微不足道的错误;-)
    对于C#

    中线程的介绍,请在使用web服务后获取用户ip并将其插入缓存一小时,这将缓存在服务器上:

    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
    }
    

    另一个想法,更新该用户的会话:我假设您有某种“批量”添加方法?感谢您的回答,让我们假设我更新会话:session[“ServiceInvoked”]=true;并询问我们是否在会话开始时询问:如果((bool)会话[“ServiceCalled”])。。。我会阻止电话。但是,如果我插入日期时间,我可以工作,因为我可以检查会话日期时间子脚本并将日期时间写入。现在,允许调用服务…@DavidRasuli您将上次更新的日期时间字段与计数器一起使用,并进行平均计算-请参见