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.
Powered by: newtelligence dasBlog 2.1.8102.813
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2012, Shawn Neal
E-mail