9

クライアントにWebサービスを提供して、クライアントが本番データベースにレコードを追加できるようにします。

最近、クライアントのプログラマーがループでサービスを呼び出し、何千回もサービスを呼び出すという事件が発生しました。

私の質問は、そのようなことを防ぐための最良の方法は何でしょうか。

私はいくつかの方法を考えました:1。サービスの入り口で、サービスを呼び出す各クライアントのカウンターを更新できますが、それはあまりにも不器用に見えます。2.このサービスを呼び出したクライアントのIPを確認し、サービスを呼び出すたびにフラグを立て、1時間ごとにフラグをリセットします。

私はもっ​​と良い方法があり、どんな提案でも適用するだろうと確信しています。

ありがとう、デビッド

4

3 に答える 3

3

まず、状況の法的側面を確認する必要があります。クライアントとの契約により、クライアントのアクセスを制限できますか?

この質問はSOの範囲外ですが、それに答える方法を見つける必要があります。すべてのリクエストを法的に処理する義務がある場合、それを回避する方法はありません。また、あなたの状況の法的分析にはすでにいくつかの制限が含まれている可能性があり、その方法でアクセスを制限することができます。これは、ソリューションに影響を及ぼします。

これらすべての問題はさておき、技術的な側面に焦点を当てて、ある種のユーザー認証を使用しますか?(そうでない場合は、なぜですか?)そうする場合は、ユーザーごとに使用することを決定したスキームを実装できます。これが最もクリーンなソリューションだと思います(IPアドレスに依存する必要はありません。これはどういうわけか醜い回避策)。

単一のユーザーを識別する方法が決まったら、いくつかの制限を実装できます。私の頭に浮かぶ最初のものはこれらです:

  1. 同期処理
    以前のすべての要求が処理された後でのみ、要求の処理を開始します。lockこれは、メインの処理メソッドのステートメントだけで実装することもできます。この種のアプローチを採用する場合は、
  2. 要求の処理間の時間遅延
    1つの処理呼び出しの後、次の呼び出しが許可される前に特定の時間が経過する必要があります。LastProcessed最も簡単な解決策は、ユーザーのセッションにタイムスタンプを保存することです。このアプローチを採用する場合は、新しいリクエストが処理される前に、新しいリクエストが届いたときにどのように応答するかを考え始める必要があります。発信者にエラーメッセージを送信しますか?私はあなたがすべきだと思います...

簡単に説明され
たステートメントを編集します。lock

スレッドセーフな操作に使用することを目的としています。構文は次のとおりです。

lock(lockObject)
{
    // do stuff
}

lockObjectオブジェクトである必要があり、通常は現在のクラスのプライベートメンバーです。その結果、両方がこのコードを実行したい2つのスレッドがある場合、lockステートメントに最初に到達したスレッドがをロックしlockObjectます。オブジェクトはすでにロックされているため、2番目のスレッドはロックを取得できません。したがって、それはただそこに座って、最初のスレッドがでブロックを出るときにロックを解放するまで待機します}。2番目のスレッドがブロックを終了するまで、2番目のスレッドがロックしてlockObjectそれを実行し、3番目のスレッドがブロックされるのをブロックできるのはこのスレッドだけです。lockObject

注意してください、スレッドセーフの全体の問題は些細なことではありません。(それについて些細なことは、プログラマーが犯す可能性のある多くの些細なエラーだけだと言えます;-) C#でのスレッド化の概要については、ここを参照してください。

于 2012-07-16T08:18:54.137 に答える
3

その方法は、セッションにカウンターを保存し、そのカウンターを使用して、1 回あたりの呼び出しが多すぎるのを防ぐことです。

ただし、ユーザーがそれを回避して毎回異なる Cookie を送信しようとする可能性がある場合*、セッションのように機能するが、ユーザーを Cookie ではなく IP に接続するカスタム テーブルを作成する必要があります。

ここでもう 1 つ、IP で基本をブロックすると、プロキシから出てくる会社全体がブロックされる可能性があります。したがって、最後の正しい方法はより複雑ですが、ip と cookie の両方をユーザーに接続し、ブラウザが cookie を許可するかどうかを知ることです。そうでない場合は、IPでブロックします。ここで難しいのは、Cookie について知ることです。すべての呼び出しで、既存のセッションに接続されている有効な Cookie を送信するように強制できます。そうでない場合、ブラウザには Cookie がありませんでした。

[ * ] Cookie はセッションに関連付けられています。
[ * ] 新しいテーブルを作成してカウンターを保持し、セッションから切断することで、セッション ロックを回避することもできます。

過去に DosAttack に使用されるコードを使用していましたが、多くのプールと難しいアプリケーションがある場合はどれもうまく機能しないため、説明したようにカスタム テーブルを使用するようになりました。これは私がテストして使用した2つのコードです

Web アプリでの Dos 攻撃

asp.net で Dos 攻撃を簡単にブロック

テーブルに保存された 1 秒あたりのクリック数を見つける方法。これは、1 秒あたりのクリック数を計算する SQL の一部です。トリックの 1 つは、クリックを追加し続け、最後のチェックから 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
于 2012-07-16T08:12:15.043 に答える
0

ユーザー IP を取得し、Web サービスを使用してから 1 時間キャッシュに挿入します。これはサーバーにキャッシュされます。

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

ユーザーが過去 1 時間に入力したかどうかを確認する必要がある場合:

if(HttpContext.Current.Cache["UserIp"] != null)
{
 //means user entered in last hour
}
于 2012-07-16T08:52:30.360 に答える