Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving between HTTP and HTTPS in ASP.NET MVC

Tags:

asp.net-mvc

So I've found the [RequiresHttps] attribute but once your in https your kind of stuck there, so to try and be able to have actions on a single url (and scheme) I've found I've ended up having to create my own ExtendedController to revert back to http for actions that don't use [RequireHttps].

Just wondering if what I'm doing is okay or if there is a better way?

public class ExtendedController : Controller
{
    protected virtual void HandleHttpRequest(AuthorizationContext filterContext)
    {
        if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("Cannot post between https and http.");
        }
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
        if (!attributes.Any(a => a is RequireHttpsAttribute))
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                this.HandleHttpRequest(filterContext);
            }
        }
    }
}
like image 789
Mark Avatar asked Nov 25 '10 13:11

Mark


1 Answers

What you have is syntatically correct, however a suggestion is to create a new Action filter that inherits from the default RequireHttpsAttribute and takes a parameter to switch between http and https.

public class RequireHttpsAttribute : System.Web.Mvc.RequireHttpsAttribute
{
    public bool RequireSecure = false;

    public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)

    {
        if (RequireSecure)
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            // non secure requested
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                HandleNonHttpRequest(filterContext);
            }
        }
    }

    protected virtual void HandleNonHttpRequest(AuthorizationContext filterContext)
    {
        if (String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            // redirect to HTTP version of page
            string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    } 
}

Then, on your action method or controller you would use:

[RequireHttps (RequireSecure = true)]

...

or

[RequireHttps (RequireSecure = false)]
like image 70
Clicktricity Avatar answered Sep 23 '22 03:09

Clicktricity