У меня есть 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;
}
}
Проблема, с которой я сталкиваюсь, хотя Я не кэширую страницу для аутентифицированного пользователя, иногда я вижу кэшированную страницу какого-то другого аутентифицированного пользователя. Это случается редко и случайно.
Если я отлаживаю через это, он работает отлично, но не тогда, когда это происходит на сайте LIVE. Я также вижу, что в браузере также создается повар ie (".As pNet .ApplicationCook ie") аутентифицированного пользователя. (Означает ли это, что кэш вывода также кеширует и куки-файлы ответов?) Если я удаляю этот повар ie, то пользователь выходит из системы, что очевидно.
В 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")]