在针对速率限制尝试解决的所有错误之后,代码无法编译

时间:2015-12-14 14:00:30

标签: 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

1 个答案:

答案 0 :(得分:0)

System.Collections.Concurrent命名空间仅适用于.Net Framework v4.0及更高版本。由于它存在于mscorlib中,因此您不可能错过该引用。 SemaphoreSlim也是如此。可能的解决方案是:

  • 如果可能,请将项目升级到较新版本的.Net。
  • 找一个有用的图书馆(Nuget?)。
  • 编写自己的并发集合类。