2

I'd like to cache the output of my MVC actions. However:

1) If I apply the OutputCacheAttribute globally, it is risky as it caches everything for all users.

2) If I apply OutputCacheAttribute globally and then apply the Authorize attribute on those actions that require authorization, that still does not solve the problem. All output is still cached regardless of the user having been authorized or not.

3) If I apply the OutputCacheAttribute (not globally but) only on select actions, and have the AuthorizeAttribute on all actions that require authorization, then there is no security threat but there is a performance cost. Every page that requires authentication will need to make a fresh Http request.

I want to find a middle-ground so that selected pages, and/or selected types of requests (HTTP GET) are cached at the client but only if the user is authenticated. If the user logs out and accesses the url of the cached page/action, he must not be able to see the content.

Is there a way to implement this?

Water Cooler v2
  • 32,724
  • 54
  • 166
  • 336

1 Answers1

2

VaryByCustom is what you want. Put this in your Global.asax file:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    // use this algorithm to determine cacheability for "IsAuthenticated"
    if ("IsAuthenticated".Equals(custom, StringComparison.OrdinalIgnoreCase))
    {
        // cache content when user is authenticated
        if (User.Identity.IsAuthenticated) return "true";

        // do not cache when user is not authenticated
        return null;
    }

    return base.GetVaryByCustomString(context, custom);
}

... then use something like this on an action method you want to cache:

[OutputCache(VaryByCustom = "IsAuthenticated", Duration = 1800,
    Location = OutputCacheLocation.Client)]
public virtual ActionResult Index()
{ ... }
Community
  • 1
  • 1
danludwig
  • 46,965
  • 25
  • 159
  • 237
  • -1 Really? I just tested this and it works. Unauthenticated users get a fresh server copy on every request, and authenticated users get a cached copy. This is exactly the same as my previous answer without the actual code. – danludwig Mar 22 '13 at 12:39