1

I have a site that needs to be secured with SSL. How can I set up a route or IIS configuration that will automatically send any request received on the non-SSL protocol over to the SSL protocol? Is this something that can be handled as a routing rule, or would it be best to use the RequireHttps attribute in the primary controller only on the methods rather than on the controller itself and detect the protocol in the Index() method?

As a note: I read this question that makes use of UrlRewriting and IIS7's Application Request Routing, but I am stuck with IIS6 and UrlRewriting is not an option for me.

Community
  • 1
  • 1
Joel Etherton
  • 37,325
  • 10
  • 89
  • 104
  • Don't rely too much on automatic redirections from `http://` to `https://`: the browser will still make the (full) initial request over plain HTTP before being redirected. See: http://stackoverflow.com/a/8765067/372643 – Bruno Jan 14 '12 at 12:52
  • @Bruno: That's a valid concern, thanks for pointing that out. It doesn't affect the small site I'm building though because it only accepts posts and the only page that would ever be initially accessed by http would be the original login. – Joel Etherton Jan 14 '12 at 13:02
  • I would advise you not to use that sort of logic. It is extremely difficult to resist the urge to make it work for you by going around the various restrictions in place. Secure data and unsecure data need to be absolutely isolated from one another. Everything that uses HTTPS is secure, whether it seems to be, or not. Everything that uses HTTP is not -- by definition...even encrypted data is not secure on HTTP. When use tunnel that way, you open a hole in your security that you might think you can control, but -- it violates the principle I outlined above. – jinzai Sep 14 '16 at 15:23

2 Answers2

2

Something like this will help:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new RequireHttpsAttribute());
    }
Arash
  • 3,628
  • 5
  • 46
  • 70
1

This is what we use. Would love to hear if it can be improved.

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

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

    // ReSharper disable RedundantAssignment
    private static void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    // ReSharper restore RedundantAssignment
    {
        validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
    }

    private static HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
    {
        return !httpContext.Request.IsSecureConnection
            ? HttpValidationStatus.IgnoreThisRequest
            : HttpValidationStatus.Valid;
    }
}

Response to comment 1

Good question, I'm not sure. HandleNonHttpsRequest comes from the base RequireHttpsAttribute. I just did an inspection in fiddler2, and there was only 1 request sent over http. However the response came back over https.

I just realized we use the above to make RequireHttps work with the output cache. You might be better off just using the RequireHttps attribute.

danludwig
  • 46,965
  • 25
  • 159
  • 237