Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Basics of Cookies in ASP.NET

Visual Studio .NET 2003

Mike Pope
Visual Basic User Education
Microsoft Corporation

January 2003

Summary: Explains how to read and write HTTP cookies in an ASP.NET Web application using Visual Basic. (18 printed pages)

Applies to

  • Microsoft® Visual Studio® .NET
  • Web Forms

Level: beginning Web programmer


What Are Cookies?
Cookie Limitations
Writing Cookies
Multi-Valued Cookies (Subkeys)
Controlling Cookie Scope
Reading Cookies
Modifying and Deleting Cookies
Cookies and Security
Checking Whether a Browser Accepts Cookies
Cookies and Session State


Cookies provide a useful means in Web applications to store user-specific information. For example, when a user visits your site, you can use cookies to store user preferences or other information. When the user visits your Web site another time, the application can retrieve the information it stored earlier.

This article provides an overview of working with cookies in ASP.NET applications. I will show you the mechanics of working with cookies in ASP.NET, such as writing them and then reading them again later. Along the way, I will explain various features and (occasional) oddities of cookies and the support in ASP.NET for them.

What Are Cookies?

A cookie is a small bit of text that accompanies requests and pages as they go between the Web server and browser. The cookie contains information the Web application can read whenever the user visits the site.

Imagine that when users request a page from your site, www.contoso.com, your application sends not just a page, but a cookie containing the date and time. When the user's browser gets the page, the browser also gets the cookie, which it stores in a folder on the user's hard disk.

Later, the user requests a page from your site again. When the user enters the URL www.contoso.com, the browser looks on the local hard disk for a cookie associated with the URL. If the cookie exists, the browser sends the cookie to your site along with the page request. Your application can then determine the date and time that the user last visited the site. You might use the information to display a message to the user, check an expiration date, or perform any other useful function.

Cookies are associated with a Web site, not with a specific page, so the browser and server will exchange the www.contoso.com cookie information no matter what page the user requests from your site. As the user visits different sites, each site might send a cookie to the user's browser as well; the browser stores all the cookies separately.

That's the basics of how cookies work. But what are they good for? In essence, cookies help Web sites store information about visitors. More generally, cookies are one way of maintaining continuity in a Web application (formally, performing state management). Except for the brief time when they are actually exchanging information, the browser and Web server are disconnected. Each request you make to a Web server is treated independently of any other request. Many times, however, it's useful for the Web server to recognize you when you request a page. For example, the Web server on a shopping site' keeps track of individual shoppers so the site can manage shopping carts and other user-specific information. A cookie therefore acts as a kind of calling card, presenting pertinent identification that helps an application know how to proceed.

Cookies are used for all sorts of purposes, all relating to helping the Web site remember you. For example, a site conducting a poll might use a cookie simply as a Boolean value to indicate whether your browser has already participated in voting so that you don't vote twice. A site that asks you to log on might use a cookie to tell itself that you've already logged on so that you don't have to keep entering your credentials.

If you'd like more background information about cookies, I recommend an article called "How Internet Cookies Work" on the Verizon Web site at http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html. The author goes into detail about what cookies are and how they are exchanged between browser and server. He also includes a good summary of what the privacy concerns are about cookies.

Incidentally, have you ever wondered why they are called "cookies"? The Jargon File (aka The New Hacker's Dictionary), version 4.2.2, has a good definition and a plausible explanation of the term's etymology. You can find the entry at http://www.catb.org/~esr/jargon/.

From here on out, I will assume that you know what cookies are and have a sense of why you might want to use them in your ASP.NET applications.

Cookie Limitations

Before we start on the mechanics of working with cookies, I will mention a couple of limitations of working with cookies. Most browsers support cookies of up to 4096 bytes. That is plenty of space for storing a few values on the user's computers, but you would not want to try to store a dataset or some other potentially large piece of data in a cookie. More practically, you probably do not want to store a big collection of user information in a cookie. Instead, you would want to store a user number or other identifier. Then, when the user visits your site again, you would use the user ID to look up user details in a database. (But see Cookies and Security for some caveats about storing user information.)

Browsers also impose limitations on how many cookies your site can store on the user's computer. Most browsers allow only 20 cookies per site; if you try to store more, the oldest cookies are discarded. Some browsers also put an absolute limit, usually 300, on the number of cookies they will accept from all sites combined.

A cookie limitation that you are likelier to run into is that users can set their browser to refuse cookies. You cannot do much to get around this problem except to avoid cookies altogether and use a different mechanism to store user-specific information. A common method for storing user information is Session state, but Session state depends on cookies, as I explain later in Cookies and Session State.

Note   For more information on state management and options for saving information in a Web application, see Introduction to Web Forms State Management and State Management Recommendations.

The more general lesson is probably that although cookies can be very useful in your application, the application should not depend on being able to store cookies. Use cookies for nice-to-have features; do not use them to support critical features. If your application must rely on cookies, you can test to see whether the browser will accept cookies. I outline a method for doing so in the section Checking Whether a Browser Accepts Cookies later in this paper.

Writing Cookies

You write a cookie using the page's Response property, which exposes an object that allows you to add to the information being rendered to the browser by the page. The Response object supports a collection named Cookies, to which you add the cookies you want to write to the browser.

Note   The Response object and the Request object, which I will discuss shortly, are properties of the page that contain, respectively, instances of the HttpResponse and HttpRequest classes. To find information in the documentation about Response and Request, look under HttpResponse and HttpRequest.

When you create a cookie, you specify several values. To start with, you specify the name of the cookie and the value to store in it. You can create multiple cookies, and each cookie must have a unique name so you can identify it later when you want to read it. (Cookies are stored by name, so if you create two cookies with the same name, one overwrites the other.)

You might also want to specify the cookie's expiration date and time. Cookies are normally written to the user's disk, where they could potentially hang around forever. You can therefore specify a date and time on which the cookie expires. When the user visits your site again, the browser first examines the collection of cookies for your site. If a cookie has expired, the browser does not send that particular cookie to the server with the page request; instead, the expired cookie is deleted. (Your site might have written multiple cookies to the user's computer; each cookie can have a separate expiration date and time.) Notice that the browser is responsible for managing cookies on the hard disk, a fact that affects what you can do with cookies in your application, as I will explain shortly.

How long should the expiration period be for a cookie? It depends on what you're using the cookie for, or to put it another way, it depends on how long your application considers the cookie value to be valid. If you're using cookies to count visitors to your site, you might decide to set expiration to a year from now on the theory that if someone hasn't visited your site in a year, you can consider that user a new visitor. In contrast, if you use cookies to store user preferences, you might set the expiration to effectively never expire (expiration of 50 years, say), since a user might find it annoying to have to reset preferences periodically. You might sometimes write a cookie that expires in seconds or minutes. Later in the paper in the section Checking Whether a Browser Accepts Cookies I have an example that creates a cookie whose practical lifetime is measured in seconds.

Note   Don't forget that users can clear the cookies on their computer any time. Even if you store cookies with long expiration times, a user might decide to delete all cookies, wiping out any settings you might have stored in cookies.

If you do not set the cookie's expiration, the cookie is created but it is not stored on the user's hard disk. Instead, the cookie is maintained as part of the user's session information. When the user closes the browser or if the session times out, the cookie is discarded. A non-persistent cookie like this is handy for information that needs to be stored for only a short time or that for security reasons should not be written to disk on the client computer. For example, non-persistent cookies are useful if the user is working on a public computer, where you do not want to write the cookie to disk.

You can add cookies to the Response.Cookies collection in a couple of ways. The following example shows two methods to accomplish the task:

Response.Cookies("userName").Value = "mike"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")
aCookie.Value = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)

The example adds two cookies to the Cookies collection, one called "userName" and the other called "lastVisit." For the first cookie, I set values of the Response.Cookies collection directly. You can add values to the collection this way because Response.Cookies derives from a specialized collection of type NameObjectCollectionBase.

For the second cookie, I create an instance of the cookie object (type HttpCookie), setting its properties, and then adding it to the Response.Cookies collection via the Add method. When you instantiate an HttpCookie object, you must pass the cookie name as part of the constructor.

Both examples accomplish the same task, namely writing a cookie to the browser. The method you use depends largely on personal preference. You might find that the second method can make it slightly easier to set cookie properties, but as you can see, the differences are not dramatic.

In both methods, the expiration value must be of type DateTime. However, the "lastVisited" value is also a date-time value. In that case, however, I had to convert the date-time value to a string. Any value that you store in a cookie is ultimately stored as a string.

Peeking at Your Cookies

You might find it useful to see the effect of creating cookies. It is easy to look at the cookies — they are text files, after all — as long as you can find them. Different browsers store cookies in different ways. I'll describe how Internet Explorer stores cookies; if you use a different browser, check the browser's Help to learn about cookie handling.

A handy way to view cookies is to have Internet Explorer find them for you. In Internet Explorer, from the Tools menu choose Internet Options. In the General tab, click Settings, and then click View Files. Internet Explorer opens a window that displays all its temporary files, including cookies. Find the files whose name begins with "Cookie:" in the window or look for text files. Double-click a cookie to open it in your default text file.

Alternatively, you can explore cookies by locating their text files on your hard disk. Internet Explorer stores the cookies for a site in a file whose name is in the format <user>@<domain>.txt, where <user> is your account name. For example, if your name is mikepope and you visit the site www.contoso.com, the cookies for that site will be in a file called mikepope@www.contoso.txt. (The name might include a sequential number, such as mikepope@www.contoso[1].txt.)

The cookie text files are user-specific, so they are isolated by account. In Windows XP, for example, you will find the cookie files in a directory with a name such as the following:

c:\Documents and Settings\<user>\Cookies

To find the cookie you are creating, you might find it helpful to sort the directory by Date Modified and look for the most recent file.

You can open the cookie with a text editor. If the file contains multiple cookies, they are separated with an asterisk (*). The first line of each cookie is its name, and the second has the values. The remaining lines have cookie housekeeping information such as the expiration date and time. There is also a simple checksum in the cookie; if you change the length of the cookie name or value, the browser will detect the tampering and will discard the cookie.

Multi-Valued Cookies (Subkeys)

The previous example uses one cookie for each value you want to store. (User name, last visit.) You can also store multiple name-value pairs in a single cookie. The name-value pairs are referred to as "keys" or "subkeys," depending on what you are reading. (Subkeys are laid out much like a query string in a URL, should you happen to be familiar with that structure.) As an example, instead of creating two separate cookies named "userName" and "lastVisit," you could create a single cookie named "userInfo" that has the subkeys "userName" and "lastVisit."

There are a couple of reasons to use subkeys instead of separate cookies. Obviously, it is tidy to put related or similar information into a single cookie. In addition, because all the information is in a single cookie, cookie attributes such as expiration apply to all the information. (Conversely, of course, if you want to assign different expiration dates to different types of information, you should store the information in separate cookies.)

A cookie with subkeys also helps you keep cookie size down. As noted earlier under Cookie Limitations, cookies are limited to 4096 bytes and you can't store more than 20 cookies per site. By using a single cookie with subkeys, you use up fewer of those 20 cookies your site is allotted. In addition, a single cookie takes up about 50 characters for overhead (expiration information, and so on), plus the length of the value that you store in it, all of which counts toward the 4K limit. If you store five subkeys instead of five separate cookies, you save the overhead of the separate cookies and can save around 200 bytes.

To create a cookie with subkeys, you can use a variation of the syntax for writing a single cookie. The following example shows two ways to write the same cookie, each with two subkeys:

Response.Cookies("userInfo")("userName") = "mike"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "mike"
aCookie.Values("lastVisit") = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)

Controlling Cookie Scope

By default, all cookies for a site are stored together on the client and all cookies are sent to the server with any request to that site — in other words, every page in a site gets all the cookies for that site. At times you might want cookie behavior to be a little more specific. You can set the scope of cookies in two ways:

  • Limit the scope of cookies to a folder on the server, which in practical terms allows you to limit cookies to an application on the site.
  • Set scope to a domain, which allows you to specify which subdomains in a domain can access a cookie.

Limiting Cookies to a Folder or Application

To limit cookies to a folder on the server, set the cookie's Path property, as here:

Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & Now.ToString
appCookie.Expires = Now.AddDays(1)
appCookie.Path = "/Application1"

Naturally, you can also write cookies out by setting Response.Cookies directly, as I explained earlier.

The path can either be a physical path under the site root or a virtual root. The effect will be that the cookie is available only to pages in the Application1 folder or virtual root. For example, if your site is called www.contoso.com, the cookie created in the previous example will be available to pages with the path http://www.contoso.com/Application1/ and to any pages beneath that folder. However, the cookie will not be available to pages in other applications such as http://www.contoso.com/Application2/ or just http://www.contoso.com/.

Tip   Some testing with Internet Explorer and the Mozilla browser suggests that the path is case sensitive. Ordinarily, URLs on Windows servers are not case sensitive, but this appears to be an exception. You can't control how users type URLs into their browsers, but if your application depends on cookies tied to a specific path, be sure that the URLs in any hyperlinks you create match the case of the Path property value.

Scoping Cookies to a Domain

By default, cookies are associated with a specific domain. For example, if your site is www.contoso.com, the cookies you write are sent to the server when users request any page from that site. (Except for cookies with a specific path value, as I explained in the section immediately preceding.) If your site has subdomains — for example, contoso.com, sales.contoso.com, and support.contoso.com — then you can associate cookies with a specific subdomain. To do so, set the cookie's Domain property, like this:

Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"

When the domain is set in this way, the cookie will be available only to pages in the specified subdomain.

You can also use the Domain property to create a cookie that can be shared among multiple subdomains. For example, set the domain as follows:

Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"

The cookie will then be available to the primary domain as well as to sales.contoso.com and support.contoso.com.

Reading Cookies

When a browser makes a request to the server, it sends the cookies for that server along with the request. In your ASP.NET applications, you can read the cookies using the Request object. The structure of the Request object is essentially the same as that of the Response object, so you can read cookies out of the Request object much the same way you wrote cookies into the Response object. The following examples show two ways to get the value of a cookie named "username" and display its value in a Label control:

If Not Request.Cookies("userName") Is Nothing Then
   Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If

If Not Request.Cookies("userName") Is Nothing Then
   Dim aCookie As HttpCookie = Request.Cookies("userName")
   Label1.Text = Server.HtmlEncode(aCookie.Value)
End If 

Before trying to get the value of a cookie, you should make sure that the cookie exists. Otherwise, you will get a System.NullReferenceException exception. Notice also that I call the HttpServerUtility.HtmlEncode method to encode the contents of a cookie before I display it in the page. I'm doing that here because I'm displaying the contents of the cookie (which you ordinarily probably do not do), and I want to be certain that a malicious user hasn't snuck executable script into the cookie. For more about cookie security, see Cookies and Security.

Note   Because different browsers store cookies differently, different browsers on the same computer won't necessarily be able to read each other's cookies. For example, if you use Internet Explorer to test a page one time, but then later use a different browser to test again, the second browser won't find the cookies saved by Internet Explorer. Of course, most people typically use the same browser for all their Web interaction, so this isn't a problem under most circumstances. However, it might come up if you are testing your application for browser compatibility, for instance.

Reading the value of a subkey in a cookie is likewise similar to setting it. Here is one way to get the value of a subkey:

If Not Request.Cookies("userInfo") Is Nothing Then
   Label1.Text = _
   Label2.text = _
End If

In the previous example, I am getting the value of the subkey "lastVisit," which I set earlier to the string representation of a DateTime value. Remember that cookies store values as strings, so if you want to use the lastVisit value as a date, you have to convert it:

Dim dt As DateTime
dt = CDate(Request.Cookies("userInfo")("lastVisit"))

The subkeys in a cookie are typed as a collection of type NameValueCollection. Therefore, another way to get an individual subkey is to get the subkeys collection and then extract the subkey value by name, as shown here:

If Not Request.Cookies("userInfo") Is Nothing Then
   Dim UserInfoCookieCollection As _
   UserInfoCookieCollection = Request.Cookies("userInfo").Values
   Label1.Text = Server.HtmlEncode(UserInfoCookieCollection("userName"))
   Label2.Text = Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If

As with setting the cookie, the method you use to read a cookie is up to you.

What's the Expiration?

You can read the name and value of a cookie, but there is not much else to learn about a cookie. You can get the Domain and Path properties, but those properties are of limited use. For example, you can read the Domain property, but of course if your page is not in the same domain as the cookie, you will not have received the cookie in the first place.

What you cannot read is the cookie's expiration date and time. It turns out that when the browser sends cookie information to the server, the browser does not include the expiration information. You can read the Expires property, but it always returns a date-time value of zero.

Earlier under Writing Cookies I mentioned that the browser is responsible for managing cookies; the Expires property is an example of this. The primary purpose of the Expires property is to help the browser perform housekeeping on its store of cookies. From the server's perspective, the cookie either exists or it does not; the expiration is not a useful piece of information on the server side. Therefore, the browser does not provide this information when it sends the cookie. If you are concerned about the expiration date of a cookie, you must reset it, as I will explain shortly under Modifying and Deleting Cookies.

To be clear, you can read the Expires property of a cookie that you have set in the Response object, before the cookie has been sent to the browser. However, you cannot get the expiration back in the Request object.

Reading Cookie Collections

The previous examples assume that you want to read a specific cookie whose name you know. You might occasionally need to read through all the cookies available to the page. To read the names and values of all the cookies available to the page, you can loop through the Request.Cookies collection using code such as the following:

Dim i As Integer
Dim output As String = ""
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output &= "Cookie name = " & Server.HtmlEncode(aCookie.Name) & "<br>"
    output &= "Cookie value = " & Server.HtmlEncode(aCookie.Value) & _
        & "<br><br>"
Label1.Text = output
Note   When you run this code, you will probably see a cookie named "ASP.NET_SessionId." That is a cookie that ASP.NET uses to store a unique identifier for your session. The session cookie is not persisted on your hard disk. For more about session cookies, see Cookies and Session State later in this article.

A limitation of the preceding example is that if the cookie has subkeys, the display shows the subkeys as a single name/value string. The cookie property HasKeys tells you whether the cookie has subkeys. If so, you can drill down into the subkey collection to get individual subkey names and values.

As I noted earlier, you can get information about subkeys out of the cookie property Values, which is a collection of type NameValueCollection. You can read subkey values from the Values collection directly by index value. The corresponding subkey names are available in the AllKeys member of the Values collection, which returns a collection of strings.

The following example shows a modification of the previous example. It uses the HasKeys property to test for subkeys, and if subkeys are detected, the example gets subkeys from the Values collection:

Dim i As Integer
Dim j As Integer
Dim output As String = ""
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
   aCookie = Request.Cookies(i)
   output &= "Name = " & aCookie.Name & "<br>"
   If aCookie.HasKeys Then
      For j = 0 To aCookie.Values.Count - 1
         subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))
         subkeyValue = Server.HtmlEncode(aCookie.Values(j))
         output &= "Subkey name = " & subkeyName & "<br>"
         output &= "Subkey value = " & subkeyValue & "<br><br>"
     output &= "Value = " & Server.HtmlEncode(aCookie.Value) & "<br><br>"
   End If
Label1.Text = output

Alternatively, you can extract the subkeys as a NameValueCollection object, as shown here:

If aCookie.HasKeys Then
   Dim CookieValues As _
      System.Collections.Specialized.NameValueCollection = aCookie.Values
   Dim CookieValueNames() As String = CookieValues.AllKeys
   For j = 0 To CookieValues.Count – 1
      subkeyName = Server.HtmlEncode(CookieValueNames(j))
      subkeyValue = Server.HtmlEncode(CookieValues(j))
      output &= "Subkey name = " & subkeyName  & "<br>"
      output &= "Subkey value = " & subkeyValue & "<br><br>"
   output &= "Value = " & aCookie.Value & "<br><br>"
End If
Note   Remember that I'm calling the Server.HtmlEncode method only because I'm displaying the values of cookies in the page. If you are merely testing the value of a cookie, you don't need to encode the value before using it.

Modifying and Deleting Cookies

At times you might want to modify a cookie, perhaps to change its value or to extend its expiration. (Remember that you cannot read a cookie's expiration date because the browser does not pass the expiration information to the server.)

You do not really directly change a cookie, of course. Although you can get a cookie from the Request.Cookies collection and manipulate it, the cookie itself still lives someplace on the user's hard disk. So modifying a cookie really consists of creating a new cookie with new values and then sending the cookie to the browser to overwrite the old version on the client.

The following example shows how you might change the value of a cookie that stores a count of the user's visits to the site:

Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    counter = 0
    counter = CInt(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)

Or alternatively:

Dim ctrCookie As HttpCookie
Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    ctrCookie = New HttpCookie("counter")
    ctrCookie = Request.Cookies("counter")
End If
counter = CInt(ctrCookie.Value) + 1
ctrCookie.Value = counter.ToString
ctrCookie.Expires = DateTime.Now.AddDays(1)

Deleting Cookies

Deleting a cookie — physically removing it from the user's hard disk — is a variation on modifying it. You cannot directly remove a cookie because the cookie is on the user's computer. However, you can get the browser to delete the cookie for you. The technique is to modify the cookie as described above (that is, create a new cookie with the same name) but to set the cookie's expiration to a date earlier than today. When the browser checks the cookie's expiration, the browser will discard the now-outdated cookie.

Deleting any one cookie is therefore the same technique as creating that cookie, except that you use a date earlier than today. The following example is slightly more interesting than deleting a single cookie — it shows one way to delete all the cookies for the current domain:

Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
   aCookie = Request.Cookies(i)
   aCookie.Expires = DateTime.Now.AddDays(-1)

Modifying or Deleting Subkeys

Modifying individual subkeys is the same as creating it in the first place:

Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

A more complicated problem is how to delete an individual subkey. You cannot simply reset the expiration date for the cookie, because that would remove the entire cookie instead of a single subkey. The solution instead is to manipulate the cookie's Values collection, which holds the subkeys. First recreate the cookie by getting it from the Request.Cookies object. You can then call the Remove method of the Values collection, passing to the Remove method the name of the subkey to delete. Then, as usual, you add the modified cookie to the Response.Cookies collection so it will be sent in its modified form back to the browser.

The following code shows how to delete a subkey. In the sample, the name of the subkey to remove is specified in a variable.

Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Expires = DateTime.Now.AddDays(1)

Cookies and Security

When you work with cookies, you must be aware of the security vulnerabilities inherent in them. By security, I do not mean privacy issues, as described in the article I referred you to under What Are Cookies? earlier; privacy is more of an issue for users who are concerned about how the information in cookies can be used. The security issues with cookies are similar to those of getting data from the client. For starters, as far as your application is concerned, cookies are another form of user input and are therefore subject to peeking and spoofing. A user can as a minimum see the data that you store in a cookie, since the cookie is available on the user's own computer. If the user is inclined, he or she can also change the cookie before the browser sends it to you.

The upshot is that you should never store secrets in a cookie — no user names, no passwords, no credit card numbers, and so on. Do not put anything in a cookie that should not be in the hands of a user or of someone who might somehow steal the cookie.

Similarly, be suspicious of information you get out of a cookie. Do not assume that the data is the same as when you wrote it out; use the same safeguards in working with cookie values that you would with data that a user has typed into a Web page. For example, I applied HTML encoding to the contents of a cookie before I displayed the value in a page. Doing so is a standard technique for sanitizing any information that you display after getting it from a user, and working with cookies is no different.

Another concern is that cookies are sent between browser and server as plain text, and anyone who can intercept your Web traffic can read the cookie. You can set a cookie property that causes the cookie to be transmitted only if the connection uses the Secure Sockets Layer (SSL, aka https://). SSL does not protect the cookie from being read or manipulated while it is on the user's computer, but it does prevent the cookie from being intercepted in transit. Again, I will not discuss SSL in this article, but be aware that you can add transmission protection to cookies. For more information about SSL, see the article Secure Sockets Layer: Protect Your E-Commerce Web Site with SSL and Digital Certificates.

Given these security issues, how can you use cookies safely? You can store non-critical data in cookies, such as a user's preferences or some other information that, if compromised, has no important effect on your application. If you do want to store sensitive information such as a user ID in a cookie, you can encrypt the cookie. One possibility is to use the ASP.NET Forms Authentication utilities to create an authentication ticket that is stored as a cookie. I do not discuss encryption in this article, but if you want to store sensitive data in a cookie, you should explore the possibilities of hiding the information from prying eyes and would-be spoofers.

You can find more information about cookies and security vulnerabilities in the article Mitigating Cross-site Scripting With HTTP-only Cookies.

Checking Whether a Browser Accepts Cookies

I mentioned earlier under Cookie Limitations the potential problem that a user might have set their browser to refuse cookies. How do you know if you can write and read cookies? No error is raised if a cookie can't be written (for example, Response.Cookies doesn't throw an exception) , because the server doesn't keep track of what happens after the page has been rendered. The browser likewise does not send any information to the server about its current cookie settings. (In case you're wondering, the HttpBrowserCapabilities.Cookies Property property does not tell you whether cookies are enabled; it only tells you whether the current browser inherently supports cookies.)

One way to determine whether cookies are accepted is by trying to write a cookie and then trying to read it back again. If you can't read the cookie you wrote, you assume that cookies are turned off in the browser.

I've put together a simple example to show how you might test whether cookies are accepted. The sample consists of two pages. On the first page, I write out a cookie, and then I redirect the browser to the second page. The second page tries to read the cookie. It in turn redirects the browser back to the first page, adding to the URL a query string variable with the results of the test.

The code for the first page looks like this:

Sub Page_Load()
   If Not Page.IsPostBack Then
      If Request.QueryString("AcceptsCookies") Is Nothing Then
           Response.Cookies("TestCookie").Value = "ok"
           Response.Cookies("TestCookie").Expires = _
           Response.Redirect("TestForCookies.aspx?redirect=" & _
           labelAcceptsCookies.Text = "Accept cookies = " & _
      End If
   End If
End Sub

The page first tests to see if this is a postback, and if not, the page looks for the query string variable (AcceptsCookies) that contains the test results. If there is no query string variable, the test hasn't been completed, so the code writes out a cookie called "TestCookie." After writing out the cookie, the sample calls Response.Redirect to transfer to the test page (TestForCookies.aspx). Appended to the URL of the test page is a query string variable called redirect containing the URL of the current page; this will allow us to redirect back to this page after performing the test.

The test page can consist entirely of code; it doesn't need to contain controls. Here's the code I used:

Sub Page_Load()
    Dim redirect As String = Request.QueryString("redirect")
    Dim acceptsCookies As String
    ' Was the cookie accepted?
    If Request.Cookies("TestCookie") Is Nothing Then
        ' No cookie, so it must not have been accepted
        acceptsCookies = 0
        acceptsCookies = 1
        ' Delete test cookie
        Response.Cookies("TestCookie").Expires = _
    End If
    Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _
End Sub

After reading the redirect query string variable, the code tries to read the cookie. For housekeeping purposes, if the cookie does in fact exist, it is immediately deleted. When the test is finished, the code constructs a new URL from the URL passed to it in the redirect query string variable. The new URL also includes a query string variable containing test results. The final step is to use the new URL to redirect the browser to the original page.

The example is quite simple, but it illustrates the basic principle of testing by trying the procedure and seeing what happens. An obvious improvement would be to keep the cookie test results in a persistent store so that the test doesn't have to be repeated each time the user views the original page. However, this is a little trickier than it looks. Cookies won't work, for obvious reasons. Another possibility would be to store the test results in Session state, but by default, Session state relies on cookies also, and if the browser won't accept cookies, Session state won't work either. The solution to this last problem is to use "cookieless" Session state. In the next section, I'll give you a very brief overview of how Session state works with cookies.

Cookies and Session State

When a user navigates to your site, the server establishes a unique session for that user that lasts for the duration of the user's visit. For each session, ASP.NET maintains a server-based structure ("Session state") where applications can store user-specific information. For more information, see the article Session State.

ASP.NET needs to be able to track a session ID for each user so that it can map the user to Session state information on the server. By default, ASP.NET uses a non-persistent cookie to store the session state. If you used the example code under "Reading Cookie Collections" in the section Reading Cookies, you probably saw among the cookies a Session state cookie.

However, if a user has disabled cookies on the browser, Session state cannot use a cookie to store the session ID and Session state doesn't work. That's why I said earlier under Checking Whether a Browser Accepts Cookies that after testing for cookies it might not be practical to store the results of the test in Session state — no cookie, no Session state.

ASP.NET offers a workaround in the form of "cookieless" sessions. You can configure your application to store Session IDs not in a cookie, but in the URLs of pages in your site. By keeping the Session ID in the URL, ASP.NET stores the ID in the browser, in a manner of speaking, and can get it back when the user requests another page.

Cookieless sessions can get around the problem of a browser that refuses cookies and allow you to work with Session state. If your application relies on Session state, you might want to configure it to use cookieless sessions. However, under some limited circumstances, if the user shares the URL with someone else — perhaps to email the URL to a colleague while the user's session is still active — then both users might end up sharing the same session, with unpredictable results.

For more information on configuring your application to use cookieless sessions, see the Knowledge Base article INFO: ASP.NET State Management Overview.

© 2015 Microsoft