# Tuesday, June 10, 2008
« Fixing Vista S4/Hibernation Insomnia | Main | Rhino Mocks Logging »

Sensitive information on your website should be encrypted between the client and the server, which generally means we need to use SSL (https).  How do we require SSL on specific MonoRail controllers or URLs?

With ASP.NET you could go into IIS and just check the "Require SSL" checkbox for a particular ASPX page.  With MonoRail, or even ASP.NET MVC, there's no corresponding resource on disk for IIS.  So how do we enable SSL at the controller level?

First off you need to add a certificate to your site in IIS, make sure you don't check "Require SSL" at the site level otherwise all requests will need to be over https. Remember we want finer grained SSL settings.

The solution I came up with was to create a MonoRail filter that gets runs before every action on a controller.  This declarative solution using attributes is much better than a base class since it can easily be added or removed from a controller.

   1: public class SecureChannelFilter : IFilter
   2: {
   3:     public const string AppKey = "SecureChannelFilterDisabled";
   4:  
   5:     public bool Perform(
   6:         ExecuteWhen exec,
   7:         IEngineContext context,
   8:         IController controller,
   9:         IControllerContext controllerContext)
  10:     {
  11:         if (context.Request.IsLocal)
  12:             return true;
  13:  
  14:         if (context.Request.Uri.Scheme == "https")
  15:             return true;
  16:  
  17:         bool disabled;
  18:         bool.TryParse(ConfigurationManager.AppSettings[AppKey], out disabled);
  19:         if (disabled)
  20:             return true;
  21:  
  22:         context.Response.StatusCode = 403;  // access forbidden
  23:         return false; // don't continue with request
  24:     }
  25: }

As you can see from the code, the filter allows local requests through without SSL but requires SSL for all other requests unless the filter has been configurationally disabled.  This allows us to run without SSL on our local development boxes.

If a request requires SSL and is not coming in over SSL, this filter then returns a 403 (Forbidden) status code which will then end up showing the IIS 403 error page.  If you wanted to get real fancy you could change your 403 error page to just redirect you back to the requested page, but using https instead of http.

To require SSL for a particular controller, like lets say a credit card controller, we would add the Filter attribute specifying the SecureChannelFilter:

   1: [Filter(ExecuteWhen.BeforeAction, typeof(SecureChannelFilter))]
   2: public class AccountDetailController
   3: {

With that in place we can feel confident that our controller will not be viewable without SSL.

Sunday, January 04, 2009 8:25:53 PM (GMT Standard Time, UTC+00:00)
I have been trying to get my monorail controllers to redirect to secure (SSL) pages using the example you provided, but it's just not working for me and I am not sure what I am missing? When the redirect happens, the URL shows http://www.mydomain.com/page instead of https://www.mydomain.com/page and the page is "blank"? I see none of the content on the page, which I am trying to access! Any thoughts on what I might be doing wrong?
Scott
Sunday, January 04, 2009 8:54:25 PM (GMT Standard Time, UTC+00:00)
The filter only ensures you are accessing the controller via HTTPS and disallows plain HTTP requests, which seems to be what is happening in your case. If you aren't using HTTPS a 403 should be returned for non-local requests. If you want it to automatically change from HTTP to HTTPS, then just modify your IIS 403 page or modify the filter to automatically change the request URI scheme to HTTPS.
Friday, April 16, 2010 1:24:39 AM (GMT Standard Time, UTC+00:00)
You have a writing task and don’t know the way to move? Don’t worry, just because the buy research paper service would aid you with the online essays very abruptly. Thence why not to use it?
Comments are closed.