How do I go about using HTTPS for some of the pages in my ASP.NET MVC based site?
Steve Sanderson has a pretty good tutorial on how to do this in a DRY way on Preview 4 at:
http://blog.codeville.net/2008/08/05/adding-httpsssl-support-to-aspnet-mvc-routing/
Is there a better / updated way with Preview 5?,
Here's a recent post from Dan Wahlin on this:
http://weblogs.asp.net/dwahlin/archive/2009/08/25/requiring-ssl-for-asp-net-mvc-controllers.aspx
He uses an ActionFilter Attribute.
Here's a blog post by Adam Salvo that uses an ActionFilter.
If you are using ASP.NET MVC 2 Preview 2 or higher, you can now simply use:
Though, the order parameter is worth noting, as mentioned here.
As Amadiere wrote, [RequireHttps] works great in MVC 2 for entering HTTPS. But if you only want to use HTTPS for some pages as you said, MVC 2 doesn't give you any love - once it switches a user to HTTPS they're stuck there until you manually redirect them.
The approach I used is to use another custom attribute, [ExitHttpsIfNotRequired]. When attached to a controller or action this will redirect to HTTP if:
It's a bit too big to post here, but you can see the code here plus some additional details.
I went accross this question and hope my solution can helps someone.
We got few problems: - We need to secure specific actions, for instance "LogOn" in "Account". We can use the build in RequireHttps attribute, which is great - but it'll redirect us back with https://. - We should make our links, forms and such "SSL aware".
Generally, my solution allows to specify routes that will use absolute url, in addition to the ability to specify the protocol. You can use this approch to specify the "https" protocol.
So, firstly I've created an ConnectionProtocol enum:
Now, I've created hand-rolled version of RequireSsl. I've modified the original RequireSsl source code to allow redirection back to http:// urls. In addition, I've put a field that allows us to determine if we should require SSL or not (I'm using it with the DEBUG pre-processor).
Now, this RequireSsl will do the following base on your Requirements attribute value: - Ignore: Won't do nothing. - Http: Will force redirection to http protocol. - Https: Will force redirection to https protocol.
You should create your own base controller and set this attribute to Http.
Now, in each cpntroller/action you'd like to require SSL - just set this attribute with ConnectionProtocol.Https.
Now lets move to URLs: We got few problems with the url routing engine. You can read more about them at http://blog.stevensanderson.com/2008/08/05/adding-httpsssl-support-to-aspnet-mvc-routing/. The solution suggested in this post is theoreticly good, but old and I don't like the approch.
My solutions is the following: Create a subclass of the basic "Route" class:
public class AbsoluteUrlRoute : Route { #region ctor
This version of "Route" class will create absolute url. The trick here, followed by the blog post author suggestion, is to use the DataToken to specify the scheme (example at the end :) ).
Now, if we'll generate an url, for example for the route "Account/LogOn" we'll get "/http://example.com/Account/LogOn" - that's since the UrlRoutingModule sees all the urls as relative. We can fix that using custom HttpModule:
Since this module is overriding the base implementation of UrlRoutingModule, we should remove the base httpModule and register ours in web.config. So, under "system.web" set:
Thats it :).
In order to register an absolute / protocol followed route, you should do:
Will love to hear your feedback + improvements. Hope it can help! :)
Edit: I forgot to include the IsCurrentConnectionSecured() extension method (too many snippets :P). This is an extension method that generally uses Request.IsSecuredConnection. However, this approch will not work when using load-balancing - so this method can bypass this (took from nopCommerce).
MVC 6 (ASP.NET Core 1.0) is working slightly different with Startup.cs.
To use RequireHttpsAttribute (as mentioned in answer by Amadiere) on all pages, you could add this in Startup.cs instead of using attribute style on each controller (or instead of creating a BaseController for all your controllers to inherit from).
Startup.cs - register filter:
For more info about design decisions for above approach, see my answer on similar question about how to exclude localhost requests from being handled by the RequireHttpsAttribute.