Joel Etherton
Joel Etherton

Reputation: 37543

MVC3: How can I route non-SSL requests automatically to the SSL protocol?

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.

Upvotes: 1

Views: 415

Answers (2)

Arash
Arash

Reputation: 4260

Something like this will help:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new RequireHttpsAttribute());
    }

Upvotes: 2

danludwig
danludwig

Reputation: 47350

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.

Upvotes: 1

Related Questions