Saturday, April 18, 2009

Switching between http to https

Sometimes we need to make few pages to run in https and few run in http, I thought to find someway where we can change the browsing of page from http to https or https to http. There is very simple way to do it.
Let's start.

1. Create a module with name Secure.cs file under App_code folder and paste the below code

using System;
using System.Linq;
using System.Web;
using System.Xml.Linq;

///
/// Summary description for Secure

///
public class Secure :IHttpModule
{
public Secure()
{
}

public void Dispose()
{
}

public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
}

private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication httpApp;
HttpContext httpContext;
try
{
httpApp = (HttpApplication)source;
httpContext = httpApp.Context;
string str = httpContext.Request.RawUrl;
XDocument xmlDoc = XDocument.Load(httpContext.Server.MapPath("Secure.xml"));
var q = from c in xmlDoc.Descendants("Page")
where c.Attribute("URL").Value.Trim().ToLower().Equals(str.Trim().ToLower())
select (string)c.Element("Secure");
foreach (string name in q)
{
if (Convert.ToBoolean(name))
{
httpContext.Response.Redirect(httpContext.Request.Url.ToString().Replace("http", "https"));
}
else
{
httpContext.Response.Redirect(httpContext.Request.Url.ToString().Replace("https", "http"));
}
}
}

catch (Exception ex)
{
}
}
}

2. In web.config, add below lines
<httpModules/>
<add name="MyHttpModule" type="Secure"/>
</httpModules/>



3. Create a XML with name secure.xml like below image, In the below xml replace your URL attribute of page element with your url(directory + page name) and in secure element specify true means, you want it to be accessed as https and if it is false , it means you want to access it as http
. You can change the xml file in production system also and you don't need to compile the application and deploy and so many other things.






Happy Coding :)

11 comments:

Ajo said...

Hi,

In step 2 (Add these lines to web.config), I cant see anything there, means no need to change web.config or there is something missing?

sumit said...

Thanx Ajo for pointing out the mistake.
I have corrected it.

Anonymous said...

Sumit,

Shouldn't the line:

if (!Convert.ToBoolean(name))

actually be:

if (Convert.ToBoolean(name))

In other words, if true then redirect as https?

sumit said...

Thanx for pointing out the mistake. I corrected it.
Thankx again for your valuable comment.

Anonymous said...

Hey,

Inspite of using an external file for handling this, the better solution would have been to add an extra custom attribute "issecure" to the each page's URL in the sitemap of the web application.

However, the proposed solution is good.

Keep Blogging!!
- Vikram Bahl

Harry Gould said...

Sumit,

Thanks for this post. One question, though: If you have a large site with many pages that don't require security but a few that do, is it necessary to list every non-secure page in the XML file? What would happen if the XML file listed only those few pages that required security and ignored the others? Can you think of any unintended consequences from this?

Harry Gould said...

Sumit,

Thanks for this post. One question, though: If you have a large site with many pages that don't require security but a few that do, is it necessary to list every non-secure page in the XML file? What would happen if the XML file listed only those few pages that required security and ignored the others? Can you think of any unintended consequences from this?

Humayun Khan said...
This comment has been removed by the author.
Humayun Khan said...

private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication httpApp;
HttpContext httpContext;
try
{
httpApp = (HttpApplication)source;
httpContext = httpApp.Context;
string rawURL = httpContext.Request.RawUrl;
XDocument xmlDoc = XDocument.Load(httpContext.Server.MapPath("~/App_Data/SecurePages.xml"));
IEnumerable decendents = xmlDoc.Descendants("Page");
bool isSecureURL = false;
for (int i = 0; i < decendents.Count(); i++)
{
string urlAttribute = decendents.ElementAt(i).Attribute("URL").Value.Trim();
if (urlAttribute.Equals(rawURL))
{
string secureElementValue = decendents.ElementAt(i).Element("Secure").Value;
if (Convert.ToBoolean(secureElementValue))
{
isSecureURL = true;
httpContext.Response.Redirect(httpContext.Request.Url.ToString().Replace("http", "https"), false);
break;
}
}
}
if (!isSecureURL)
{
string actualURL = httpContext.Request.Url.ToString();
if (actualURL.StartsWith("https"))
{
httpContext.Response.Redirect(actualURL.Replace("https", "http"), false);
}
}
}

catch (Exception ex)
{
}
}

Those of you who just want to include secure pages in the XML file, use the above code.

Anonymous said...

Hi dear publisher! Thank you very much for your valuable article! I found it useful and very simple. What thing you didn't mention for us is that, how we generate SSL certeficate for local testing and bind it to our web site
Thank
Doji

Anonymous said...

@ADas
nice post... quite helpful.
As per my knowledge.. when we host web app in IIS we specify the bindings with "http" or "https". My question here is, can we have both bindings running in parallel at same time for few pages using "http" and some other pages using "https"? Can someone share more insight to this?
Thanks in advance.

Site Meter