ASP.NET MVC 缓存 - 登录用户被缓存
ASP.NET MVC Caching - Logged-in user gets cached
我有一个 ASP.NET MVC 应用程序,我在其中实现了自定义缓存过滤器,代码如下:
public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
public NonAuthenticatedOnlyCacheAttribute()
{
Duration = 600; /*default cache time*/
}
private bool _partialView;
public bool PartialView
{
get { return _partialView; }
set
{
_partialView = value;
if (_partialView)
{
VaryByCustom = "user";
}
}
}
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;
}
}
我面临的问题是,即使我没有为经过身份验证的用户缓存页面,有时我也会看到其他一些经过身份验证的用户的缓存页面。这种情况很少发生且随机发生。
如果我通过这个调试,它工作得很好,但当它出现在实时站点上时就不行了。
我还看到,经过身份验证的用户的 cookie (".AspNet.ApplicationCookie") 也会在浏览器中创建。 (这是否意味着输出缓存也在缓存响应 cookie?)
如果我删除此 cookie,那么用户将被注销,这很明显。
在Global.asax中,我有以下代码:
public override string GetVaryByCustomString(HttpContext context, string value)
{
if (value.Equals("culture") || value.Equals("user"))
{
var customString = Thread.CurrentThread.CurrentUICulture.Name;
if (context.User.Identity.IsAuthenticated)
{
customString = $"{context.User.Identity.Name}-{customString}";
}
return customString;
}
return base.GetVaryByCustomString(context, value);
}
并且在控制器上,缓存了以下属性
[NonAuthenticatedOnlyCacheAttribute(Location = System.Web.UI.OutputCacheLocation.Server, Duration = 600, VaryByCustom = "user")]
我认为问题可能是您没有告诉 ASP.NET 您的意思:
VaryByCustom = "user"
也许您这样做了,但是您的 post 中没有包含代码。
在您的 Global.asax.cs 中,您将拥有类似的内容:
public override string GetVaryByCustomString(HttpContext context, string arg)
{
if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase))
{
var user = context.User.Identity.Name; // TODO here you have to pick an unique identifier from the current user identity
return string.Format("{0}@{1}", userIdentifier.Name, userIdentifier.Container);
}
return base.GetVaryByCustomString(context, arg);
}
您可以找到关于此的更多信息here and here。
我有一个 ASP.NET MVC 应用程序,我在其中实现了自定义缓存过滤器,代码如下:
public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
public NonAuthenticatedOnlyCacheAttribute()
{
Duration = 600; /*default cache time*/
}
private bool _partialView;
public bool PartialView
{
get { return _partialView; }
set
{
_partialView = value;
if (_partialView)
{
VaryByCustom = "user";
}
}
}
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;
}
}
我面临的问题是,即使我没有为经过身份验证的用户缓存页面,有时我也会看到其他一些经过身份验证的用户的缓存页面。这种情况很少发生且随机发生。
如果我通过这个调试,它工作得很好,但当它出现在实时站点上时就不行了。 我还看到,经过身份验证的用户的 cookie (".AspNet.ApplicationCookie") 也会在浏览器中创建。 (这是否意味着输出缓存也在缓存响应 cookie?) 如果我删除此 cookie,那么用户将被注销,这很明显。
在Global.asax中,我有以下代码:
public override string GetVaryByCustomString(HttpContext context, string value)
{
if (value.Equals("culture") || value.Equals("user"))
{
var customString = Thread.CurrentThread.CurrentUICulture.Name;
if (context.User.Identity.IsAuthenticated)
{
customString = $"{context.User.Identity.Name}-{customString}";
}
return customString;
}
return base.GetVaryByCustomString(context, value);
}
并且在控制器上,缓存了以下属性
[NonAuthenticatedOnlyCacheAttribute(Location = System.Web.UI.OutputCacheLocation.Server, Duration = 600, VaryByCustom = "user")]
我认为问题可能是您没有告诉 ASP.NET 您的意思:
VaryByCustom = "user"
也许您这样做了,但是您的 post 中没有包含代码。 在您的 Global.asax.cs 中,您将拥有类似的内容:
public override string GetVaryByCustomString(HttpContext context, string arg)
{
if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase))
{
var user = context.User.Identity.Name; // TODO here you have to pick an unique identifier from the current user identity
return string.Format("{0}@{1}", userIdentifier.Name, userIdentifier.Container);
}
return base.GetVaryByCustomString(context, arg);
}
您可以找到关于此的更多信息here and here。