OK, I went and downloaded Vista Beta 1 and played for a while. There are some nice things but all in all incremental improvements over XP. My beef though is with the interface and the hype. For years I heard about this super secret 3d interface being developed, it was supposed to make OSX users jealous and makes users want to run out and buy the product when released.
Someone please tell me that this is not it, is that seriously the best you got? I work with OSX almost every day and tell people that Longhorn should have a UI that makes Cupertino shake but this makes me look like an idiot.
Scoble? Someone? Please tell me the goods are still hiding in Redmond and you are going to pull some last second, “Oh yeah, here is the fancy stuff”
Sometimes you feel secure, sometimes you don’t. Better put, sometimes a page needs to be secured and sometimes it does not.
One of the things I wanted to do on a recent project was avoid unnecessary page encryption when the content did not require it to be. This may sound like a silly problem but when you consider that in the logical click stream of a user they may go from a page with sensitive data to a non-sensitive page and then back a forth between pages that contain secret information, you can see where you are wasting cycles encrypting pages that don’t need it.
This seemed to me like a common problem and I expected that the IIS would have an easy way to deal with this problem and while IIS does allow you to require SSL for a specific file it does not fail with elegance. By that I mean that when you visit the page which requires SSL using a normal HTTP session, you get a server error (Http status codes 403.4, 403.5 I think) that tells you this page must be viewed securely. While for some users this is not a big deal, just make the change to the URL – most people get really confused at this point; and heck if the darn thing knew it needed to be secure then why not just become secure. Furthermore, when considering this challenge outside my personal scope I knew that going the IIS route for this solution did not seem the best path because in lots of cases developers don’t have access to make IIS changes. So as I venture to find a way to make my application do this I am quite sure that ASP.NET has some great, built-in functionality which will do for me what I am attempting; after much searching I came to the conclusion that Request.IsSecureConnection is as good as it gets in the framework.
Other people have proposed solutions in the past, today I even ran across one which prompted me to write this; Matt Sollars has an excellent two part article on Code Project which details his solution to this problem involving httpModules and extending the configuration of asp.net.
I actually rolled a solution similar to Matt’s but was unhappy with the general complexity of it; I wanted something simple and the problem scope seemed so limited that there had to be some way to achieve this in a relatively performant manner without having to write a lot of code.
OK, that is a lot of build up, now to the point…
I found a way by extending the Page class that you can automatically move people in and out of secure pages with as little as one line of code per page! Here is how you do it.
First thing you will need to do is add some code to your base Page class; almost every single ASP.NET tips/tricks/good practices/yada/yada/yada article tells you that you should extend System.Web.UI.Page with common functionality; if you are not doing this already, shame on you.
To the base page class add a private boolean field to store the data indicating whether a page is secure
private bool _RequireSSL;
Also add a property which wraps this field
[Browsable(true)]
[Description("Indicates whether or not this page should be forced into or out of SSL")]
public virtual bool RequireSSL
{
get
{
return _RequireSSL;
}
set
{
_RequireSSL = value;
}
}
Note: You will notice that the property is decorated with a couple of attributes, the first, “Browsable” tells VS.NET to show this property in the design time property window allowing you to indicate in that window what the value of the property would be, doing this can make things a bit easier and save you even needing to write the single line of code per page needed to implement the functionality; setting the property effectively writes the code for you. The “Description” attribute tells VS.NET what text should show at the bottom of the Properties window when this property is selected.
Next, we are going to add the actual method to our code which will do the magic. You will notice that this method has two other attributes, the first will tell VS.Net when debugging to skip over this part, no need to see it; it works. The second attribute indicates that we only want to run this code when we have compiled with a SECURE compilation constant defined, this saves us having to deal with SSL certs and such on development machines as we can define that constant only in build configurations that will be deployed to an environment with the certificate such as staging or production.
[System.Diagnostics.DebuggerStepThrough()]
[System.Diagnostics.Conditional("SECURE")]
private void PushSSL()
{
const string SECURE = "https://";
const string UNSECURE = "http://";
//Force required into secure channel
if(RequireSSL && Request.IsSecureConnection==false)
Response.Redirect(Request.Url.ToString().Replace( UNSECURE , SECURE ));
//Force non-required out of secure channel
if(!RequireSSL && Request.IsSecureConnection==true)
Response.Redirect(Request.Url.ToString().Replace( SECURE , UNSECURE ));
}
The logic here is quite simple, if the RequireSSL property is set to TRUE and the Request is not a secure connection then we need to perform a redirect. That redirect will take the Request.Url which is the full URL of the request, convert it to a string and then replace http:// with https:// and send the user on to the https version of the page. The second conditional statement does the same thing only in reverse, taking a user out of SSL if the page is not required to be secure. You could toy with the actual string replacement if you wish, for example you might want to only analyze the first few characters of a string in the case the some form of "http" is embedded later in your URL (maybe you have other URLs; in your URL) that is up to you – for the sake of making it as easy to understand as possible I chose the simplest route.
Now we have our field, our property and our method, the only thing left is the implementation. To make this work for our pages we need to override OnInit in our page class…
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
PushSSL();
}
As you can see from the code above we are really only adding to OnInit, not changing the behavior any as the first thing we do is call the base member. Our second line of code calls our method which will run the process of checking our page is moving it in and out of the secure channel.
Now we have all of the pieces in place, to implement this on an actual page there is really only one line of code which you can write of let VS.NET write for you; an un-initialized boolean is by default false so unless you are trying to make a page secure there is really no reason you will need to do this. In the case you do need to make a page secure you should set the RequireSSL property equal to True on the page; this should be done in the InitializeComponent method…
private void InitializeComponent()
{
this.RequireSSL = true;
//Other initialization code would be here also
}
The setting of this property can also be achieved by pulling up the design time properties of your page, navigating to the Page member in the property drop down list and setting the property manually. This will write the line of code for you.
Normally this is where professional writers recap and wrap up but I have pretty much said all there is to say, it works…it is not perfect but it does the job, if you are into this kind of thing I would also suggest looking at Matt’s article and deciding what solution is best for you.
related stuff to check out:
MSDN on Conditional Attributes
MSDN on the Browsable Attribute
MSDN on the Description Attribute
The Debugger Step Through Attribute
Matt Sollars solution @ Code Project
HTTP Status Codes
Extending System.Web.UI.Page
http://applematters.com/index.php/section/comments/423/
Sometimes when I read stuff like this I seriously think it was originally written for “The Onion”
Having a point to point argument with this guy would be like beating up a kid in a wheelchair but I thought I would bring up a few of the wackier points for good laughs.
“Shoddy software practices are forced on programmers due to incompetent managers which in turn produces the mess that is Longhorn.”
– Those terrible managers and shoddy practices, that’s the problem. Please tell me though, do you know any of these managers? Can you detail these bad practices? Have you even seen the “mess” that is Longhorn?
“Then on the server side Microsoft has finally realized that they are fighting a losing war.”
– Yeah and the fact that so many people are tossing Windows 2003 for other things just amplifies this…
“Now factor in the ITMS and how profitable it has been.”
– Forget the fact that Microsoft makes twice as much PROFIT in one month than ITMS has done in total revenue its entire lifetime.
“News flash! Longhorn is going to be drastically overshadowed by Leopard and Macs running Intel.”
- So everyone will be excited for the 200 people who still use Macs while no one will care the 200 million + users will be getting an upgrade.
“Throw all of the current Windows code away. All of it. Everything from 9x to XP to Longhorn, everything has to go. It’s all crap and its time to jettison those reeking piles of poorly written, buggy code.”
– I love proclamations from people who expose themselves in this way; I wonder how many lines of code this guy has written (hint: HTML does not count).
“There is no need to make IE so deeply attached to your kernel. Bad things happen when you do stuff like that.”
– OK, can you even give me a salient definition of a kernel? IE has never been part of the kernel, it will not be in Longhorn either.
And the one I like best is his suggestion for what Microsoft should do; suggestion number one, top of the list...Admit Defeat!
Ha! I love a good laugh.