MVC RequireHttps entire site

asp.net MvcSsl

asp.net Mvc Problem Overview


I have read the previous posts about using the RequireHttpsAttribute to secure individual controllers:

https://stackoverflow.com/questions/1639707/asp-net-mvc-requirehttps-in-production-only

but is there a way to apply this to the entire site? Due to my host (discountasp.net) I cannot use the "RequireSSL IIS" setting.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

Register the RequireHttpsAttribute as a global filter.

In global.asax:

protected void Application_Start()
{
    GlobalFilters.Filters.Add(new RequireHttpsAttribute());

    //... other stuff
}

Solution 2 - asp.net Mvc

I ended up using IIS URL Rewrite 2.0 to force the site to switch to HTTPS. This code in web.config does the trick:

  <system.webServer>
    <!-- This uses URL Rewrite 2.0 to force the entire site into SSL mode -->
    <rewrite xdt:Transform="Insert">
      <rules>
        <rule name="Force HTTPS" enabled="true">
          <match url="(.*)" ignoreCase="false" />
          <conditions>
            <add input="{HTTPS}" pattern="off" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

Solution 3 - asp.net Mvc

You could always add a check at the application level in your global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
   if (!HttpContext.Current.Request.IsSecureConnection)
   {
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
                                 + HttpContext.Current.Request.RawUrl);
   }
}

Solution 4 - asp.net Mvc

Just to bring this answer upto date for MVC 3 and above use the following in your Filterconfig.cs file within the App_start folder

        filters.Add(new RequireHttpsAttribute());

Obviously you will need your servers IIS configured to use a valid SSL certificate, cheap certs can be purchased here: https://www.namecheap.com/ i think the last time i purchased one it was $9 per domain per year.

Solution 5 - asp.net Mvc

In your FilterConfig.cs apply this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
     // only if Debug is not enabled, do not require https for local development
     if (!HttpContext.Current.IsDebuggingEnabled)
          filters.Add(new RequireHttpsAttribute());

     //... any other filters
}

That should force your app to use https on every page.

Solution 6 - asp.net Mvc

This isn't using RequireHttps but I think it's a better solution because it catches the redirect sooner in the MVC Lifecycle.

public class RedirectModule : IHttpModule
{
    private HttpApplication _context;

    public void Init(HttpApplication context)
    {
        _context = context;
        _context.PostResolveRequestCache += HttpRedirect;
    }

    public void HttpRedirect(Object src, EventArgs args)
    {
        if (_context.Request.Url.Scheme == Uri.UriSchemeHttp)
        {
            //Redirect to https
            var scheme = Uri.UriSchemeHttps + "://";
            var authority = _context.Request.Url.Authority;
            var url = _context.Request.RawUrl;

            var redirectTo = scheme + authority + url;
            _context.Response.PermanentRedirect(redirectTo);
        }
    }

    public void Dispose() { }
}

The idea came from this article.

You can register the module in your Web.config or inside the Global.asax. I'll show you in the web.cofig.

<system.webServer>
    <modules>
        <add name="ConfigModuleName" type="Your.Namespace.RedirectModule"/>
    </modules>
</system.webServer>

Solution 7 - asp.net Mvc

MVC 6 (ASP.NET Core 1.0) works slightly different in it's way of registering filters:

Startup.cs - AddMvc with filter for RequireHttpsAttribute:

public void ConfigureServices(IServiceCollection services)
{
    // TODO: Register other services

    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(RequireHttpsAttribute));
    });
}

Design decisions explained:

  1. Use filter in Startup.cs for global setup (since we want this to apply everywhere). Startup should be responsible for registering and setting up all global rules. If your company employ a new developer, she would expect to find global setup in Startup.cs.
  2. Use RequireHttpsAttribute logic since it's proven (by Microsoft). Never use "magical" strings like "http://" and "https://" when it can be avoided by reusing a Microsoft component created to provide the same logic.

If you are running your MVC website in localhost without SSL:

  • http://localhost:1337/ (no SSL)
  • https://localhost:1337/ (SSL)

Consider looking at how to run without SSL in localhost while still requiring https it in production.

Note:

As an alternative, we could make a "class BaseController : Controller" and make all our controllers inherit from "BaseController" (instead of Controller). Then we only have to set the attribute 1 global place (and don't need to register filter in Startup.cs).

Some people prefer the attribute style.

Example of usage:

[RequireHttpsAttribute]
public class BaseController : Controller
{
    // Maybe you have other shared controller logic..
}

public class HomeController : BaseController
{
    // Add endpoints (GET / POST) for Home controller
}

Solution 8 - asp.net Mvc

In Global.asax.cs, use "RegisterGlobalFilters" to register global attributes.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new RequireHttpsAttribute());
    //e.g. filters.Add(new HandleErrorAttribute());
    //e.g. filters.Add(new System.Web.Mvc.AuthorizeAttribute());            
}

Solution 9 - asp.net Mvc

You could use a base class for all of your controllers, and decorate that with the require ssl attribute.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCodeGrueView Question on Stackoverflow
Solution 1 - asp.net MvchwiechersView Answer on Stackoverflow
Solution 2 - asp.net MvcCodeGrueView Answer on Stackoverflow
Solution 3 - asp.net MvcTodd SmithView Answer on Stackoverflow
Solution 4 - asp.net MvcAlex StephensView Answer on Stackoverflow
Solution 5 - asp.net MvcjoegreenteaView Answer on Stackoverflow
Solution 6 - asp.net Mvcchristo8989View Answer on Stackoverflow
Solution 7 - asp.net MvcNick NieblingView Answer on Stackoverflow
Solution 8 - asp.net MvcDhanuka777View Answer on Stackoverflow
Solution 9 - asp.net MvcDanPView Answer on Stackoverflow