Click here to Skip to main content
15,886,199 members
Articles / Web Development / ASP.NET

Switching Between HTTP and HTTPS Automatically: Version 2

Rate me:
Please Sign up or sign in to vote.
4.91/5 (223 votes)
7 Feb 2011CPOL18 min read 3.5M   680  
An article on automatically switching between HTTP and HTTPS protocols without hard-coding absolute URLs
Imports System.Web

''' <summary>
''' The SSLHelper class provides Shared methods for ensuring that a page is rendered 
''' securely via SSL or unsecurely.
''' </summary>
Public Class SSLHelper

	Private Const UnsecureProtocolPrefix As String = "http://"
	Private Const SecureProtocolPrefix As String = "https://"

	''' <summary>
	''' Requests the current page over a secure connection, if it is not already.
	''' </summary>
	''' <param name="hostPath">The host path to redirect to if needed.</param>
	''' <param name="maintainApplicationPath">
	'''		A flag indicating whether or not to maintain the current application path if
	'''		a redirect is necessary.
	'''	</param>
	Public Shared Sub RequestSecurePage(ByVal settings As SecureWebPageSettings)
		' Is this request secure?
		Dim RequestPath As String = HttpContext.Current.Request.Url.ToString()
		If RequestPath.StartsWith(UnsecureProtocolPrefix) Then
			' Is there a host path to redirect to?
			If settings.EncryptedUri Is Nothing OrElse settings.EncryptedUri.Length = 0 Then
				' Replace the protocol of the requested URL with "https"
				RequestPath = RequestPath.Replace(UnsecureProtocolPrefix, SecureProtocolPrefix)
			Else
				' Build the URL with the "https" protocol
				RequestPath = BuildUrl(True, settings.MaintainPath, settings.EncryptedUri, settings.UnencryptedUri)
			End If

			' Redirect to the secure page
			HttpContext.Current.Response.Redirect(RequestPath, True)
		End If
	End Sub

	''' <summary>
	''' Requests the current page over an insecure connection, if it is not already.
	''' </summary>
	''' <param name="hostPath">The host path to redirect to if needed.</param>
	''' <param name="maintainApplicationPath">
	'''		A flag indicating whether or not to maintain the current application path if
	'''		a redirect is necessary.
	'''	</param>
	Public Shared Sub RequestUnsecurePage(ByVal settings As SecureWebPageSettings)
		' Is this request secure?
		Dim Request As HttpRequest = HttpContext.Current.Request
		Dim RequestPath As String = Request.Url.ToString()
		If RequestPath.StartsWith(SecureProtocolPrefix) Then
			' Is there a different URI to redirect to?
			If settings.UnencryptedUri Is Nothing OrElse settings.UnencryptedUri.Length = 0 Then
				' Replace the protocol of the requested URL with "http"
				RequestPath = RequestPath.Replace(SecureProtocolPrefix, UnsecureProtocolPrefix)
			Else
				' Build the URL with the "http" protocol
				RequestPath = BuildUrl(False, settings.MaintainPath, settings.EncryptedUri, settings.UnencryptedUri)
			End If

			' Test for the need to bypass a security warning
			Dim Bypass As Boolean
			If settings.WarningBypassMode = SecurityWarningBypassMode.AlwaysBypass Then
				Bypass = True
			ElseIf settings.WarningBypassMode = SecurityWarningBypassMode.BypassWithQueryParam AndAlso Not Request.QueryString(settings.BypassQueryParamName) Is Nothing Then
				Bypass = True

				' Remove the bypass query parameter from the URL
				Dim NewPath As New System.Text.StringBuilder(RequestPath)
				Dim i As Integer = RequestPath.IndexOf(settings.BypassQueryParamName)
				NewPath.Remove(i, settings.BypassQueryParamName.Length + Request.QueryString(settings.BypassQueryParamName).Length + 1)

				' Remove any abandoned "&" character
				If i >= NewPath.Length Then
					i = NewPath.Length - 1
				End If
				If NewPath(i) = "&"c Then
					NewPath.Remove(i, 1)
				End If

				' Remove any abandoned "?" character
				i = NewPath.Length - 1
				If NewPath(i) = "?"c Then
					NewPath.Remove(NewPath.Length - 1, 1)
				End If

				RequestPath = NewPath.ToString()
			Else
				Bypass = False
			End If

			' Output a redirector for the needed page to aSub a security warning
			If (Bypass) Then
				Dim Response As HttpResponse = HttpContext.Current.Response
				Response.Clear()

				' Refresh header
				Response.AddHeader("Refresh", String.Concat("0;URL=", RequestPath))

				' JavaScript to replace the current location
				Response.Write("<html><head><title></title>")
				Response.Write("<!-- <script language=""javascript"">window.location.replace(""")
				Response.Write(RequestPath)
				Response.Write(""");</script> -->")
				Response.Write("</head><body></body></html>")

				Response.End()

				Return
			End If

			' Redirect to the insecure page
			HttpContext.Current.Response.Redirect(RequestPath, True)
		End If
	End Sub

	''' <summary>
	''' Builds a URL from the given protocol and appropriate host path. The resulting URL 
	''' will maintain the current path if requested.
	''' </summary>
	''' <param name="secure">Is this to be a secure URL?</param>
	''' <param name="maintainPath">Should the current path be maintained during transfer?</param>
	''' <param name="encryptedUri">The URI to redirect to for encrypted requests.</param>
	''' <param name="unencryptedUri">The URI to redirect to for standard requests.</param>
	''' <returns></returns>
	Private Shared Function BuildUrl(ByVal secure As Boolean, ByVal maintainPath As Boolean, ByVal encryptedUri As String, ByVal unencryptedUri As String) As String
		' Get the current request
		Dim Request As HttpRequest = HttpContext.Current.Request
		Dim CurrentUrl As String = Request.Url.ToString()

		' Build the needed URL
		Dim Url As New System.Text.StringBuilder

		' Host path (secure.mysite.com/)
		If secure Then
			Url.Append(encryptedUri)
		Else
			Url.Append(unencryptedUri)
		End If
		Url.Append("/")

		If maintainPath Then
			' Calculate the length of the appropriate target URI
			Dim RootLength As Integer = 0
			If CurrentUrl.StartsWith(UnsecureProtocolPrefix) Then
				RootLength = UnsecureProtocolPrefix.Length + unencryptedUri.Length
			Else
				RootLength = SecureProtocolPrefix.Length + encryptedUri.Length
			End If

			' Get the path from the current URL after the target URI
			Url.Append(CurrentUrl.Substring(RootLength))
		Else
			' Append just the current page
			Url.Append(CurrentUrl.Substring(CurrentUrl.LastIndexOf("/"c) + 1))
		End If

		' Replace any double slashes with a single slash
		Url.Replace("//", "/")

		' Prepend the protocol
		If secure Then
			Url.Insert(0, SecureProtocolPrefix)
		Else
			Url.Insert(0, UnsecureProtocolPrefix)
		End If

		Return Url.ToString()
	End Function

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
I began programming on my Commodore 64 at around the age of 12. After migrating to DOS and then Windows, I decided to take on the Web. Several languages and platforms later, I have settled in with .NET nicely. I am currently the owner of a software consulting company and lead application developer for a learning-based technology consultation company.

The love of a finished application is usually at war with the desire to improve it as soon as it's released (they're never really finished).

Comments and Discussions