c# - 解决了限速尝试的所有错误后,代码无法编译

标签 c# error-handling compiler-errors compiler-warnings

最终目标是对可能被强行暴露出敏感信息的参数进行速率限制。

第一个文件是DisplayMessage.cs,具有以下代码:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using BLL;
using DOL;

public partial class DisplayMessage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetNoStore();

        //Security Fix for Session Fixation
        if (Session["User"] != null && Session["AuthToken"] != null
           && Request.Cookies["AuthToken"] != null)
        {
            if (!Session["AuthToken"].ToString().Equals(
                       Request.Cookies["AuthToken"].Value))
            {
                Response.Redirect("~/default.aspx");
            }
        }
        else
        {
            Response.Redirect("~/default.aspx");
        }

        //if (!this.IsPostBack)
        //{
            BindFullMessage(Convert.ToInt32(Request.QueryString["MessageId"]));
        //}

            //Rate Limiting Security Vulnerability
            using (RateGate rateGate = new RateGate(2, TimeSpan.FromSeconds(1)))
            {
                for (int i = 0; i < 1000; i++)
                {
                    rateGate.WaitToProceed();
                    BindFullMessage(Convert.ToInt32(Request.QueryString["MessageId"]));
                }

            } 

    }
    private void BindFullMessage(int MessageId)
    {
        CommonMethods commonMethod = new CommonMethods();
        lblFullMessage.Text = commonMethod.GetFullMessageByMessageId(MessageId);        
    }
}

文件RateLim.cs如下:
using System;
using System.Web;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;





/// <summary>
/// Summary description for RateLim
/// </summary>

public class RateGate : IDisposable
{
    // Semaphore used to count and limit the number of occurrences per
    // unit time.
    private readonly System.Threading.SemaphoreSlim _semaphore;

    // Times (in millisecond ticks) at which the semaphore should be exited.
    private readonly System.Collections.Concurrent.ConcurrentQueue<int> _exitTimes;

    // Timer used to trigger exiting the semaphore.
    private readonly Timer _exitTimer;

    // Whether this instance is disposed.
    private bool _isDisposed;

    /// <summary>
    /// Number of occurrences allowed per unit of time.
    /// </summary>
    public int Occurrences { get; private set; }

    /// <summary>
    /// The length of the time unit, in milliseconds.
    /// </summary>
    public int TimeUnitMilliseconds { get; private set; }

    /// <summary>
    /// Initializes a <see cref="RateGate"/> with a rate of <paramref name="occurrences"/> 
    /// per <paramref name="timeUnit"/>.
    /// </summary>
    /// <param name="occurrences">Number of occurrences allowed per unit of time.</param>
    /// <param name="timeUnit">Length of the time unit.</param>
    /// <exception cref="ArgumentOutOfRangeException">
    /// If <paramref name="occurrences"/> or <paramref name="timeUnit"/> is negative.
    /// </exception>
    public RateGate(int occurrences, TimeSpan timeUnit)
    {
        // Check the arguments.
        if (occurrences <= 0)
            throw new ArgumentOutOfRangeException("occurrences", "Number of occurrences must be a positive integer");
        if (timeUnit != timeUnit.Duration())
            throw new ArgumentOutOfRangeException("timeUnit", "Time unit must be a positive span of time");
        if (timeUnit >= TimeSpan.FromMilliseconds(UInt32.MaxValue))
            throw new ArgumentOutOfRangeException("timeUnit", "Time unit must be less than 2^32 milliseconds");

        Occurrences = occurrences;
        TimeUnitMilliseconds = (int)timeUnit.TotalMilliseconds;

        // Create the semaphore, with the number of occurrences as the maximum count.
        _semaphore = new System.Threading.SemaphoreSlim(Occurrences, Occurrences);

        // Create a queue to hold the semaphore exit times.
        _exitTimes = new System.Collections.Concurrent.ConcurrentQueue<int>();

        // Create a timer to exit the semaphore. Use the time unit as the original
        // interval length because that's the earliest we will need to exit the semaphore.
        _exitTimer = new Timer(ExitTimerCallback, null, TimeUnitMilliseconds, -1);
    }

    // Callback for the exit timer that exits the semaphore based on exit times 
    // in the queue and then sets the timer for the nextexit time.
    private void ExitTimerCallback(object state)
    {
        // While there are exit times that are passed due still in the queue,
        // exit the semaphore and dequeue the exit time.
        int exitTime;
        while (_exitTimes.TryPeek(out exitTime)
                && unchecked(exitTime - Environment.TickCount) <= 0)
        {
            _semaphore.Release();
            _exitTimes.TryDequeue(out exitTime);
        }

        // Try to get the next exit time from the queue and compute
        // the time until the next check should take place. If the 
        // queue is empty, then no exit times will occur until at least
        // one time unit has passed.
        int timeUntilNextCheck;
        if (_exitTimes.TryPeek(out exitTime))
            timeUntilNextCheck = unchecked(exitTime - Environment.TickCount);
        else
            timeUntilNextCheck = TimeUnitMilliseconds;

        // Set the timer.
        _exitTimer.Change(timeUntilNextCheck, -1);
    }

    /// <summary>
    /// Blocks the current thread until allowed to proceed or until the
    /// specified timeout elapses.
    /// </summary>
    /// <param name="millisecondsTimeout">Number of milliseconds to wait, or -1 to wait indefinitely.</param>
    /// <returns>true if the thread is allowed to proceed, or false if timed out</returns>
    public bool WaitToProceed(int millisecondsTimeout)
    {
        // Check the arguments.
        if (millisecondsTimeout < -1)
            throw new ArgumentOutOfRangeException("millisecondsTimeout");

        CheckDisposed();

        // Block until we can enter the semaphore or until the timeout expires.
        var entered = _semaphore.Wait(millisecondsTimeout);

        // If we entered the semaphore, compute the corresponding exit time 
        // and add it to the queue.
        if (entered)
        {
            var timeToExit = unchecked(Environment.TickCount + TimeUnitMilliseconds);
            _exitTimes.Enqueue(timeToExit);
        }

        return entered;
    }

    /// <summary>
    /// Blocks the current thread until allowed to proceed or until the
    /// specified timeout elapses.
    /// </summary>
    /// <param name="timeout"></param>
    /// <returns>true if the thread is allowed to proceed, or false if timed out</returns>
    public bool WaitToProceed(TimeSpan timeout)
    {
        return WaitToProceed((int)timeout.TotalMilliseconds);
    }

    /// <summary>
    /// Blocks the current thread indefinitely until allowed to proceed.
    /// </summary>
    public void WaitToProceed()
    {
        WaitToProceed(Timeout.Infinite);
    }

    // Throws an ObjectDisposedException if this object is disposed.
    private void CheckDisposed()
    {
        if (_isDisposed)
            throw new ObjectDisposedException("RateGate is already disposed");
    }

    /// <summary>
    /// Releases unmanaged resources held by an instance of this class.
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);

    }

    /// <summary>
    /// Releases unmanaged resources held by an instance of this class.
    /// </summary>
    /// <param name="isDisposing">Whether this object is being disposed.</param>
    protected virtual void Dispose(bool isDisposing)
    {
        if (!_isDisposed)
        {
            if (isDisposing)
            {
                // The semaphore and timer both implement IDisposable and 
                // therefore must be disposed.
                _semaphore.Dispose();
                _exitTimer.Dispose();

                _isDisposed = true;
            }
        }
    }
}

以下是错误提示:

enter image description here

我究竟做错了什么?

编辑:构建版本+设置屏幕快照已添加,以供社区要求引用

enter image description here

enter image description here

最佳答案

System.Collections.Concurrent namespace 仅在.Net Framework v4.0及更高版本中可用。由于它存在于mscorlib中,因此不可能丢失该引用。 SemaphoreSlim 也是如此。可能的解决方案是:

  • 如果可能,将您的项目升级到新版本的.Net。
  • 查找一个会有所帮助的库(Nuget?)。
  • 编写您自己的并发集合类。
  • 关于c# - 解决了限速尝试的所有错误后,代码无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34268880/

    相关文章:

    c# - 锁定字段或局部变量?

    c# - Visual Studio 版本控制

    MySQL 错误 1822 : Failed to add foreign key constraint; missing index for contraint BUT index exists

    android - 在编译期间,如何修复 android studio 中 Room 中复杂 sql 语句验证的错误?

    Java:标记 "n"上存在语法错误,++ 预计在此标记之后

    c# - 时间复杂度——将 O(N²) 重构为 O(N)

    C#:了解事件语法

    php - 无法序列化和反序列化对象以删除对象元素PHP

    python - 捕获停止执行我的 Python 脚本的错误

    c - 未定义的函数引用和 ld 返回 1 退出状态错误。没有语法错误。