Home  | Source Code  | Tools  | Links  | Search  |  
¿Habla Español?
Source Code Sections
ASP.NET General Internet Windows Explorer Windows Forms Old VB6 Code
Info
Download
qse.zip (12Kb)

Valid XHTML 1.0!

Valid CSS!

HttpModule to encrypt query strings

This HttpModule encrypts and decrypts the query strings that are passed to pages with the URL. With a little help of Reflection (to hack the Request.QueryString collection) and Regular Expressions (to change the page links before they are sent to the client) these classes automatically encrypt and decrypt the parameters without any special code in the pages. Just use Respose.QueryString and write links like you usually do and the module will do the rest.

Installing the module

To add the module to a web application just copy the dll to its bin directory and add the module in the web.config file.  You can also  add the dll to the project references if you want or have to encrypt a query string in the application code.

<configuration>
   <system.web>
      ...
      ...
      ...
      <httpModules>
         	<add type="Edanmo.Web.Security.QueryStringEncryptionModule,Edanmo.Web.QSE" 
              name="QSE" />
      </httpModules>
   </system.web>
</configuration>

How it works

When the module it's initialized the code add handlers for two application events: PreRequestHandlerExecute and PostRequestHandlerExecute.

Private Sub Init(ByVal context As System.Web.HttpApplication) Implements IHttpModule.Init

    ' Set the handler for the PreRequestHandlerExecute event
    AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

    ' Set the handler for the PostRequestHandlerExecute event
    AddHandler context.PostRequestHandlerExecute, AddressOf OnPostRequestHandlerExecute

End Sub

The PreRequestHandlerExecute event is raised before the page handler is called and will be used to decrypt the query string sent to the page.  PostRequestHandlerExecute is called after the page handler finishes and will be used to set a response filter which will find and encrypt the query strings that are in the response before it is sent to the client.

The OnPreRequestHandlerExecute method

As I said before, this method gets the encrypted query string and decrypts it. The interesting part of this is that the decrypted parameters are added to the QueryString collection, and is interesting because QueryString is a read-only collection! Here is were Reflection comes handy. Using Reflection we can access private members of a class and that's what the code does. It gets the private IsReadOnly property of the collection and sets it to false. After doing that we can add and remove values from it.

' Get the PropertyInfo for the NameValueCollection.IsReadOnly property
Dim isReadOnly As PropertyInfo = queryCollection.GetType.GetProperty("IsReadOnly", _
                                     BindingFlags.Instance Or BindingFlags.NonPublic)

' Set the query string collection to read/write
isReadOnly.SetValue(queryCollection, False, Nothing)

After doing that the code decrypts the query string and adds each parameter to the collection and removes the encrypted one. At the end it sets the collection is set back to read-only.

The OnPostRequestHandlerExecute method

This method sets the response filter stream that will encrypt the query strings in the response before it is sent to the client. Before setting the filter it checks if the response content type is text/html to set the filter only for HTML content (you don't want binary data changed!).

' Get the application object
Dim app As HttpApplication = CType(sender, HttpApplication)

With app.Response

    ' Set the response filter stream if the
    ' content type is text/html
    If .ContentType.ToLower = "text/html" Then
        .Filter = New QueryStringEncryptionResponseFilter(.Filter)
    End If

End With

The QueryStringEncryptionResponseFilter class

A response filter class is a class that inherits the System.IO.Stream class. Only the Write method is important for this module. It gets the data sent by the page handler, using three regular expressions (one for the action attribute of <form>, one for the src attribute of any tag and one for the href attribute of any tag) it finds the query strings and encrypts them and then write the data in the base stream.

Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer)

    ' Get the HTML from the buffer
    Dim html As String = UTF8.GetString(buffer, offset, count)

    ' Encrypt the query string in the action attribute of forms
    html = _regexForm.Replace(html, AddressOf QueryStringMatchEvaluator)

    ' Encrypt the query string in the src attributes
    html = _regexSrc.Replace(html, AddressOf QueryStringMatchEvaluator)

    ' Encrypt the query string in the href attributes
    html = _regexHRef.Replace(html, AddressOf QueryStringMatchEvaluator)

    ' Write the new response to the base stream
    Dim buffer2() As Byte = UTF8.GetBytes(html)
    _stream.Write(buffer2, 0, buffer2.Length)

End Sub