首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在ASP.NET MVC中为认证用户关闭输出缓存?

如何在ASP.NET MVC中为认证用户关闭输出缓存?
EN

Stack Overflow用户
提问于 2010-01-21 22:31:26
回答 3查看 4.6K关注 0票数 15

我有一个ASP.NET MVC应用程序。我需要缓存一些页面,但是,对于未经认证的用户,只有

我尝试在下面的GetVaryByCustomString实现中使用VaryByCustom="user"

public override string GetVaryByCustomString(HttpContext context, string custom)
{
  if (custom == "user")
  {
      if (context.User.Identity.IsAuthenticated)
      {
        return context.User.Identity.Name;
      }
      else
      {
        return "";
      }
  }  

  return base.GetVaryByCustomString(context, custom);
}

然而,这并不是我所需要的,因为页面仍然被缓存。唯一不同的是,现在为每个用户单独缓存。

一种可能的解决方案是每次用户通过身份验证时都返回Guid.NewGuid(),但在我看来这是对资源的巨大浪费。

你有什么建议给我吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-01-23 02:18:42

下面是我所做的:

public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
      var httpContext = filterContext.HttpContext;

      if (httpContext.User.Identity.IsAuthenticated)
      {
        // it's crucial not to cache Authenticated content
        Location = OutputCacheLocation.None;
      }

      // this smells a little but it works
      httpContext.Response.Cache.AddValidationCallback(IgnoreAuthenticated, null);

      base.OnResultExecuting(filterContext);
    }

    // This method is called each time when cached page is going to be
    // served and ensures that cache is ignored for authenticated users.
    private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
      if (context.User.Identity.IsAuthenticated)            
        validationStatus = HttpValidationStatus.IgnoreThisRequest;          
      else          
        validationStatus = HttpValidationStatus.Valid;          
    }
}

非常感谢Craig Stuntz,他为我指明了正确的方向,我在不知不觉中否决了他的答案。

票数 32
EN

Stack Overflow用户

发布于 2012-03-14 10:03:11

属性一般都是缓存的,然后你需要存储原始位置。如果您访问记录的页面,它会将位置设置为None,然后当您以匿名身份访问时,它仍然为None。

public class AuthenticatedOnServerCacheAttribute : OutputCacheAttribute
{
    private OutputCacheLocation? originalLocation;

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var httpContext = filterContext.HttpContext;

        if (httpContext.User.Identity.IsAuthenticated)
        {
            originalLocation = originalLocation ?? Location;
            Location = OutputCacheLocation.None;
        }
        else
        {
            Location = originalLocation ?? Location;
        }

        base.OnResultExecuting(filterContext);
    }
}
票数 12
EN

Stack Overflow用户

发布于 2012-04-25 21:00:36

公认的答案是正确的,但它不适用于以这种方式缓存部分视图。我组合了这两种方法:GetVaryByCustomString和set Duration to the minimum -用于局部视图,AddValidationCallback方法用于页面。实际上,只使用第一种方法是可能的,但第二种方法看起来不是很昂贵-它不会每次都调用OnResultExecuting,而只调用已注册的处理程序。

因此,自定义缓存属性类

public class CacheAttribute : OutputCacheAttribute
{   

    public CacheAttribute()
    {
      Duration = 300;  /*default cache time*/
    }

    private bool _partialView;

    /// <summary>
    /// Set true if Partial view is cached
    /// </summary>
    public bool PartialView
    {
      get { return _partialView; }
      set
      {
        _partialView = value;
        if ( _partialView ) {
          VaryByCustom = "Auth";
        }
      }
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if ( PartialView ) OnCachePartialEnabled( filterContext );
        else OnCacheEnabled(filterContext);

        base.OnResultExecuting( filterContext );     
    }

    private OutputCacheLocation? originalLocation;
    private int? _prevDuration;
    protected void OnCachePartialEnabled(ResultExecutingContext filterContext)
    {
      var httpContext = filterContext.HttpContext;

      if ( !_prevDuration.HasValue) _prevDuration = Duration;
      Duration = httpContext.User.Identity.IsAuthenticated ? 1 : _prevDuration.Value;
    }

    protected void OnCacheEnabled(ResultExecutingContext filterContext)
    {
      var httpContext = filterContext.HttpContext;

      if ( httpContext.User.Identity.IsAuthenticated ) {
        // it's crucial not to cache Authenticated content
        originalLocation = originalLocation ?? Location;
        Location = OutputCacheLocation.None;
      }
      else {
      Location = originalLocation ?? Location;
    }

      // this smells a little but it works
      httpContext.Response.Cache.AddValidationCallback( IgnoreAuthenticated, null );      
    }

    // This method is called each time when cached page is going to be
    // served and ensures that cache is ignored for authenticated users.
    private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
      validationStatus = context.User.Identity.IsAuthenticated 
        ? HttpValidationStatus.IgnoreThisRequest 
        : HttpValidationStatus.Valid;
    }
}

覆盖Global.asax.cs中的GetVaryByCustomString方法

public override string GetVaryByCustomString(HttpContext context, string custom)
{ 
    if ( custom == "Auth" ) {
      //do not cache when user is authenticated
      if ( context.User.Identity.IsAuthenticated ) {
        return base.GetVaryByCustomString( context, custom );
      }
      return "NotAuth";
    }     
    return base.GetVaryByCustomString( context, custom );
}

像这样使用它:

[Cache]
public virtual ActionResult Index()
{
    return PartialView();
}

[ChildActionOnly, Cache(PartialView=true)]
public virtual ActionResult IndexPartial()
{
    return PartialView();
}

更新:我还在这里添加了Fujiy的修复

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2109928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档