Download the Source
A common method to pass values between aspx pages is to use a query
string. Using this method, the information often contained is indifferent
to user modification or user access. When information does need to be
secured, another method is employed, such as encrypted cookies or session
management. However, these methods are not always available. Session
management is not preferred in some situations, and users may choose to not
accept cookies in other cases. In another scenario, you may want to give out a
URL (e.g., in an e-mail) with which you do not want tampered, or maybe a URL in
which you can expire after a certain amount of time. In this article, we’ll look
at ways to secure your URLs from tampering using secure query strings.
What about URL Sessions?
Why not just use a URL-based session management solution? While a
URL-based session solution allows you to essentially store encrypted session
data within a query string, it does not allow you to create URLs that can be
linked across applications, nor does it allow you to generate URLs with a preset
expiration period. Also, a URL can last a lot longer than a session, which
usually has a timeout period of just 20 or 30 minutes. Of course, just like any
other technical problem, there are different viable solutions. Which solution is
employed is ultimately up to your best judgment given the specific problem that
you are solving.
The Query String
A secure query string will not expose its values in plain text, nor will it
allow the client to successfully change a query string value. When you normally
build a query string, you simply append name/value pairs as follows:
http://localhost/sample.aspx?myKey=myValue&myKey2=myValue2
A secure query string works a little different. Here is what a secure query
string may look like:
http://localhost/sample.aspx?x=a89rtgeitrgt4igjbht389tggitdgoiy45yh45
The values are now “garbled” from the public eye, and any tampering will
corrupt the data and make it unusable. As illustrated above, instead of passing
the name/value pairs as separate query string parameters, we pass a single value
(in this case, “x”) with an encrypted string that contains the same data.
All of the rules that apply to a normal query string also apply to a secure
query string. For example, every parameter and value must be properly
URL-encoded (ref: System.Web.HttpUtility.UrlEncode()). You must also keep
your query string within Internet Explorer's 2 KB limit. Keep in mind that
encryption will increase the size of your original string depending on the type
of encryption employed.
Show Me Some Code Already!
Implementing a secure query string is simple, and works almost identically to
any other NameValueCollection. The following code
simply instantiates the SecureQueryString object and adds
a couple of parameters to it.
// Create the
queryString object
SecureQueryString qs = new SecureQueryString();
// Add name/value pairs.
qs["Name"] =
"TSHAK";
qs["SSN"] = "000-00-0000";
Now let’s generate a URL with your name/value pairs encrypted. To do this, we
simply call the ToString() method:
string url =
"DestPage.aspx?x=" + qs.ToString();
You’ll see that I used the query string parameter “x”. You can name any
parameter that you like, or not use a named parameter at all. I used the
“x” for illustration purposes.
Now that we’ve generated the URL, we need a way to retrieve the values from
the receiving page. Because the values are encrypted, we can no longer use
the Request object to pull our values. Fortunately,
as shown in the code snippet below, the process is very similar:
// Simply pass the
encrypted string into the constructor
SecureQueryString qs = new SecureQueryString(Request["x"]);
// Now access the NameValueCollection
string Name = qs["Name"];
string SSN = qs["SSN"];
All I did is pass the encrypted string into a new instance of SecureQueryString, and now I get access to the original values
in virtually the same fashion as I would if I was using the Request object.
Expiring URLs
While preventing the tampering of query strings is compelling in and of
itself, another compelling feature is the ability to expire a URL at a specific
point in time. This feature can be useful when you want to allow someone
limited access to content without requiring the person to have an account on
your system. For example, you may want to e-mail a URL to a user in which
they can hand out to friends, but only allow that URL to stay active for a few
days.
Implementing an expiring URL simply requires you to set the ExpireTime property of a SecureQueryString instance. Building on the earlier example,
here’s a query string that will expire in one hour:
// Create the
queryString object
SecureQueryString qs = new SecureQueryString();
// Add name/value pairs.
qs["Name"] =
"TSHAK";
qs["SSN"] = "000-00-0000";
// Set the
expiration time for one hour from now
qs.ExpireTime =
DateTime.Now.AddHours(1);
When you retrieve the values from the requesting page using the SecureQueryString object, it will throw an ExpiredQueryStringException if the data has
expired. Otherwise, you’ll get the data just as I showed you earlier.
As a side note, some developers may prefer to not throw an exception in this
scenario. An alternative is to have something like an IsExpired property that can be checked when the values are
retrieved. Another is to simply clear the underlying NameValueCollection if the data has expired.
Final Thoughts
There is a lot that happens “under the hood” that can be customized. For
example, the component used to illustrate my methodolgy here uses the 3DES
algorithm for encryption, but you may wish to implement a different algorithm
such as AES. We also discussed different methods for handling expired
data. The code is yours, so hack it to your liking!
For those of you concerned with performance, you’ll need to do your own
testing. A lot depends on the encryption algorithm that you choose. In my
experience, heavy use of SecureQueryString does have a
small performance impact. However, I have not seen numbers that exceed what
would be generally acceptable for this type of functionality.
Included in the download is a sample Web application as well as all of the
source code for the SecureQueryString component. If you have any problems with
the example code or if you have any questions in general, please post to this
article’s forum so that everyone can benefit from your question.
Secure query strings are a good solution for passing data securely between
pages and applications. However, this is only one of many possible solutions and
you should remember to always consider existing solutions, such as encrypted
cookies and session management.