Caching content only for non-authenticated users

2019-03-21 01:05发布

For a web-site, I want to cache the pages ONLY for users who are not authenticated - authenticated users do not get cached content (since they will be updating and need to see results right away).

I know how to vary the cache for each user using VaryByCustom: Link1 Link2

...But I can't figure out how to turn off caching entirely for authenticated users.

What to do?

Edit

The code below has a problem if there is already a cached version of the page from an unauthenticated user. Basically the authenticated user will be served the unauthenticated view of things.

However, this link here has solution that works: Link

4条回答
你好瞎i
2楼-- · 2019-03-21 01:42

Taking inspiration from the Link1 you posted, as easy-to-code idea is that you could alter the output of the GetVaryByCustomString override as follows:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "IsLoggedIn")
    {
        if (context.Request.Cookies["anon"] != null)
        {
           if (context.Request.Cookies["anon"].Value == "false")
           {
              return "auth";
           }
        }
        return Guid.New().ToString();
    }
    else
    {
        return base.GetVaryByCustomString(context, arg);
    }
}

This is not really an answer as technically the authenticated user's output will still be cached, but it does satisfy the requirement of having authenticated users see whatever the results are right away. The downside is that you'll need to keep the cache duration/TTL small enough so your cache doesn't get flooded but large enough that anonymous users gain some benefit from it.

Another alternative is to write your own Action Filter to do the caching, and add support in there for anonymous-only caching. This is far more in 'roll your own' territory though. See Klopfenstein's old post or Steve Sanderson's on this for a starting point. They lack many of the other features of OutputCache (it keys on the whole route data for instance), but you can make it work to your own specifications.

查看更多
Fickle 薄情
3楼-- · 2019-03-21 01:43

You may want to create two controllers, one for authenticated users (where you don't cache), one for non authenticated users (where you cache). Then you can refractor the logic in the controllers to a common "business layer object" to keeping your code DRY and unit testable.

查看更多
狗以群分
5楼-- · 2019-03-21 01:57

Use this as a global action filter.

public class NoCacheForAuthenticatedUsersAttribute: ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if(filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        }
    }
}
查看更多
登录 后发表回答