3

I have an ASP.NET MVC 3 application with an action that uses both the RequireHttps and OutputCache attributes:

[RequireHttps]
[OutputCache(Duration = 14400, VaryByCustom = "CurrentUser"]
public ActionResult VersionB()
{
  return View();
}

When I navigate to that page, I get redirected to HTTPS, as expected.

However, after that initial page load, I can still access the page via HTTP. If I remove the OutputCache attribute, I can no longer access the page via HTTP.

It seems as if the OutputCache disregards HTTPS, thus allowing insecure access to the page. Is it even possible to cache an action that is served over HTTPS?

1
  • 1
    I faced the same issue and removed the OutputCache attribute to get around.. Commented Apr 8, 2011 at 9:29

1 Answer 1

10

The [RequireHttps] attribute implementation is flawed and doesn't take into account caching.

Here's a fix:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class MyRequireHttpsAttribute : RequireHttpsAttribute
{
    protected virtual bool AuthorizeCore(HttpContextBase httpContext)
    {
        return httpContext.Request.IsSecureConnection;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (!AuthorizeCore(filterContext.HttpContext))
        {
            this.HandleNonHttpsRequest(filterContext);
        }
        else
        {
            var cache = filterContext.HttpContext.Response.Cache;
            cache.SetProxyMaxAge(new TimeSpan(0L));
            cache.AddValidationCallback(this.CacheValidateHandler, null);
        }
    }

    private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
        validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context));
    }

    protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
    {
        if (!AuthorizeCore(httpContext))
        {
            return HttpValidationStatus.IgnoreThisRequest;
        }
        return HttpValidationStatus.Valid;
    }
}

and then:

[MyRequireHttps]
[OutputCache(Duration = 14400, VaryByCustom = "CurrentUser"]
public ActionResult VersionB()
{
    return View();
}
Sign up to request clarification or add additional context in comments.

1 Comment

Even with MVC 5.2 this has not been fixed natively. This fix still works great!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.