【问题标题】:Cache objects don't expire ASP Net C#缓存对象不会过期 ASP Net C#
【发布时间】:2014-12-23 21:47:47
【问题描述】:

我正在为我的 Web 表单应用程序开发缓存功能。我想跟踪用户输入用户名(相同或不同)以阻止该 IP 的次数。

我使用 1 分钟的绝对过期时间,以便缓存对象在创建后 1 分钟后过期,无论上次访问如何。

但是,当我运行应用程序(使用 Visual Studio 开发服务器)时,除非我重建项目,否则缓存不会过期。

我在网上搜索了一些解决方案,比如设置滑动过期为NoSlidingExpiration,也可以使用自定义的计数器类来存储数据。

我还找到了一个使用system.web 标签内的 web.config 缓存元素的解决方案:

<caching>
  <cache disableExpiration="false"/>
</caching>

缓存仍然没有过期。任何帮助都会很棒。这是我正在使用的代码。

private int CacheCheck()
{
    // Create the keys used and retrive the values from the cahce
    IncrementingCacheObject cacheUsername = Cache[KeyUsername] as IncrementingCacheObject;
    IncrementingCacheObject cacheDiffAttempts = Cache[KeyDiffAttempts] as IncrementingCacheObject;
    IncrementingCacheObject cacheSameAttempts = Cache[KeySameAttempts] as IncrementingCacheObject;

    // Check if the username exists in cache
    if (cacheUsername != null)
    {
        if (cacheUsername.Username.Equals(this.txtUserName.Text, StringComparison.InvariantCultureIgnoreCase))
        {
            if (cacheSameAttempts != null)
            {
                cacheSameAttempts.Count++;
                this.Cache[KeySameAttempts] = cacheSameAttempts;
            }
            else
            {
                cacheSameAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
                Cache.Insert(KeySameAttempts, cacheSameAttempts, null, cacheSameAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration);
            }
        }
        else
        {
            if (cacheDiffAttempts != null)
            {
                cacheDiffAttempts.Count++;
                this.Cache[KeyDiffAttempts] = cacheDiffAttempts;
            }
            else
            {
                cacheDiffAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
                Cache.Insert(KeyDiffAttempts, cacheDiffAttempts, null, cacheDiffAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration);
            }
        }

        // Set the last used username value in the Cache to the value in the text box
        cacheUsername.Username = this.txtUserName.Text;
        this.Cache[KeyUsername] = cacheUsername;
    }
    else
    {
        cacheUsername = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        cacheDiffAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        cacheSameAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        Cache.Insert(KeyUsername, cacheUsername, null, cacheUsername.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration);
        Cache.Insert(KeySameAttempts, cacheSameAttempts, null, cacheSameAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration);
        Cache.Insert(KeyDiffAttempts, cacheDiffAttempts, null, cacheDiffAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration);
    }

    cacheUsername = Cache[KeyUsername] as IncrementingCacheObject;
    cacheDiffAttempts = Cache[KeyDiffAttempts] as IncrementingCacheObject;
    cacheSameAttempts = Cache[KeySameAttempts] as IncrementingCacheObject;
    // Check whether any log in attempts have surpassed the threshold and return a value to indicate what kind of log in was detected
    if (cacheDiffAttempts != null && cacheDiffAttempts.Count >= MaxLogAttemptsBeforeBan)
    {
        return 0;
    }

    if (cacheSameAttempts != null && cacheSameAttempts.Count >= MaxLogAttemptsBeforeBan)
    {
        return 1;
    }

    return -1;
}

    /// <summary>
    /// This will reset the cache to blank/starting values.
    /// </summary>
    private void ResetCache()
    {
        Cache.Remove(KeyUsername);
        Cache.Remove(KeySameAttempts);
        Cache.Remove(KeyDiffAttempts);
    }

    // Class used to store objects in the cache
    private class IncrementingCacheObject
    {
        public string Username;
        public int Count;
        public DateTime ExpireDate;
    }

当用户登录成功后,在页面被重定向之前,会调用ResetCache()方法。

【问题讨论】:

  • 您是否查看过使用会员服务提供商的最大登录尝试次数? msdn.microsoft.com/en-us/library/…
  • 您是否设置了缓存策略的绝对过期属性?
  • 限制数据库交互可能是一个可以说是合理的理由...但会提供更长期的安全性...如果您的缓存在用户多次登录尝试中途过期怎么办...如果您将尝试限制为 5 次,并且他们每天进行 4 次,持续 6 个月,直到他们进入?
  • @RXC 我建议使用 CacheItemPriority 并将其设置得尽可能高,同时牢记您的系统限制,以尽量减少正在擦除的缓存。
  • @RXC 另外,您为什么不像在您使用的解决方案中那样使用 HttpContext.Current.Cache ?这很可能会混淆您当前的缓存未过期问题。

标签: c# asp.net caching webforms


【解决方案1】:

不要使用DateTime.UtcNowCache 期望以本地时间表示的绝对过期时间。使用DateTime.Now.AddMinutes

【讨论】:

  • 我最初使用DateTime.Now,但它也不起作用,但我可以重试我所做的所有更改。如果它有效,我会更新。
  • @RXC 尝试使用 DateTimeOffset
  • @Igor 恐怕你错了……msdn.microsoft.com/en-us/library/4y13wyk9%28v=vs.110%29.aspx "插入对象过期并从缓存中删除的时间。避免本地时间可能出现的问题,例如从标准时间更改为夏令时,请使用 UtcNow 而不是 Now 作为此参数值。如果您使用绝对过期,则 rollingExpiration 参数必须为 NoSlidingExpiration。"附言我不会投反对票;)
  • @PaulZahra - 你是对的,他们必须通过 DateTime.Kind 来区分 UTC 和当地时间。在代码示例中,他们仍然使用DateTime.Now
【解决方案2】:

我发现了我遇到的问题。

我在网上找到了这个解决方案:

Stackoverflow Questions

我需要更改一些代码才能工作。我必须删除对缓存的任何直接分配并使用插入方法。这是新代码。另外,改用HttpContect.Current.Cache

private int CacheCheck()
{
    // Create the keys used and retrive the values from the cahce
    IncrementingCacheObject cacheUsername = Cache[KeyUsername] as IncrementingCacheObject;
    IncrementingCacheObject cacheDiffAttempts = Cache[KeyDiffAttempts] as IncrementingCacheObject;
    IncrementingCacheObject cacheSameAttempts = Cache[KeySameAttempts] as IncrementingCacheObject;

    // Check if the username exists in cache
    if (cacheUsername != null)
    {
        if (cacheUsername.Username.Equals(this.txtUserName.Text, StringComparison.InvariantCultureIgnoreCase))
        {
            if (cacheSameAttempts != null)
            {
                cacheSameAttempts.Count++;
            }
            else
            {
                cacheSameAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
            }

            HttpContext.Current.Cache.Insert(KeySameAttempts, cacheSameAttempts, null, cacheSameAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
        }
        else
        {
            if (cacheDiffAttempts != null)
            {
                cacheDiffAttempts.Count++;
            }
            else
            {
                cacheDiffAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
            }

            HttpContext.Current.Cache.Insert(KeyDiffAttempts, cacheDiffAttempts, null, cacheDiffAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
        }

        // Set the last used username value in the Cache to the value in the text box
        cacheUsername.Username = this.txtUserName.Text;
    }
    else
    {
        cacheUsername = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        cacheDiffAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        cacheSameAttempts = new IncrementingCacheObject { Count = 0, ExpireDate = DateTime.UtcNow.AddMinutes(1), Username = this.txtUserName.Text };
        HttpContext.Current.Cache.Insert(KeySameAttempts, cacheSameAttempts, null, cacheSameAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
        HttpContext.Current.Cache.Insert(KeyDiffAttempts, cacheDiffAttempts, null, cacheDiffAttempts.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    }

    HttpContext.Current.Cache.Insert(KeyUsername, cacheUsername, null, cacheUsername.ExpireDate, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null);

    // Check whether any log in attempts have surpassed the threshold and return a value to indicate what kind of log in was detected
    if (cacheDiffAttempts != null && cacheDiffAttempts.Count >= MaxLogAttemptsBeforeBan)
    {
        return 0;
    }

    if (cacheSameAttempts != null && cacheSameAttempts.Count >= MaxLogAttemptsBeforeBan)
    {
        return 1;
    }

    return -1;
}

/// <summary>
/// This will reset the cache to blank/starting values.
/// </summary>
private void ResetCache()
{
    HttpContext.Current.Cache.Remove(KeyUsername);
    HttpContext.Current.Cache.Remove(KeySameAttempts);
    HttpContext.Current.Cache.Remove(KeyDiffAttempts);
}

// Class used to store objects in the cache
private class IncrementingCacheObject
{
    public string Username;
    public int Count;
    public DateTime ExpireDate;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-20
    • 2020-09-27
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 2016-01-28
    相关资源
    最近更新 更多