Using Browser Cookies


Cookies were introduced into the world with the first version of the Netscape browser. The developers at Netscape invented cookies to solve a problem that plagued the Internet at the time. There was no way to make money because there was no way to create a shopping cart.

Note

You can read Netscape's original cookie specification at http://home.netscape.com/newsref/std/cookie_spec.html.


Here's how cookies work. When a web server creates a cookie, an additional HTTP header is sent to the browser when a page is served to the browser. The HTTP header looks like this:

Set-Cookie: message=Hello 


This Set-Cookie header causes the browser to create a cookie named message that has the value Hello.

After a cookie has been created on a browser, whenever the browser requests a page from the same application in the future, the browser sends a header that looks like this:

Cookie: message=Hello 


The Cookie header contains all the cookies that have been set by the web server. The cookies are sent back to the web server each time a request is made from the browser.

Notice that a cookie is nothing more than a little bit of text. You can store only string values when using a cookie.

You actually can create two types of cookies: session cookies and persistent cookies. A session cookie exists only in memory. If a user closes the web browser, the session cookie disappears forever.

A persistent cookie, on the other hand, can last for months or even years. When you create a persistent cookie, the cookie is stored permanently by the user's browser on the user's computer. Internet Explorer, for example, stores cookies in a set of text files contained in the following folder:

\Documents and Settings\[user]\Cookies 


The Mozilla Firefox browser, on the other hand, stores cookies in the following file:

[View full width]

\Documents and Settings\[user]\Application Data\Mozilla\Firefox\Profiles\[random folder name]\Cookies.txt


Because different browsers store cookies in different locations, cookies are browser relative. If you request a page that creates a cookie when using Internet Explorer, the cookie doesn't exist when you open Firefox or Opera.

Furthermore, notice that both Internet Explorer and Firefox store cookies in clear text. You should never store sensitive informationsuch as social security numbers or credit card numbersin a cookie.

Note

Where does the name cookie come from? According to the original Netscape cookie specification, the term cookie was selected "for no compelling reason." However, the name most likely derives from the UNIX world in which a "magic cookie" is an opaque token passed between programs.


Cookie Security Restrictions

Cookies raise security concerns. When you create a persistent cookie, you are modifying a file on a visitor's computer. There are people who sit around all day dreaming up evil things that they can do to your computer. To prevent cookies from doing horrible things to people's computers, browsers enforce a number of security restrictions on cookies.

First, all cookies are domain relative. If the Amazon website sets a cookie, then the Barnes and Noble website cannot read the cookie. When a browser creates a cookie, the browser records the domain associated with the cookie and doesn't send the cookie to another domain.

Note

An image contained in a web page might be served from another domain than the web page itself. Therefore, when the browser makes a request for the image, a cookie can be set from the other domain. Companies, such as DoubleClick, that display and track advertisements on multiple websites take advantage of this loophole to track advertisement statistics across multiple web sites. This type of cookie is called a third-party cookie.


The other important restriction that browsers place on cookies is a restriction on size. A single domain cannot store more than 4096 bytes. This size restriction encompasses the size of both the cookie names and the cookie values.

Note

Internet Explorer, version 5.0 or higher, supports a feature named the userData behavior. The userData behavior enables you to persist far more data than a cookie (10240KB for an intranet site and 1024 for an Internet site). To learn more about the userData behavior, visit the Microsoft MSDN website (msdn.microsoft.com).


Finally, most browsers restrict the number of cookies that can be set by a single domain to no more than 20 cookies (but not Internet Explorer). If you attempt to set more than 20 cookies, the oldest cookies are automatically deleted.

Note

The White House's Office of Management and Budget bans all federal websites from creating persistent cookies unless there is a "compelling need." See http://www.whitehouse.gov/omb/memoranda/m00-13.html.

The National Security Agency web site (www.nsa.gov) recently got into trouble for creating persistent cookies. They stopped using persistent cookies after they received a barrage of complaints from privacy advocates.

Personally, I think that this cookie paranoia is crazy, but you need to be aware of it.


Because of all the security concerns related to cookies, all modern browsers provide users with the option of disabling cookies. This means that unless you are building an Intranet application and you control every user's browser, you should attempt to not rely on cookies. Strive to use cookies only when storing non-crucial information.

That said, many parts of the ASP.NET Framework rely on cookies. For example, Web Parts, Forms Authentication, Session state, and anonymous Profiles all depend on cookies by default. If you are depending on one of these features anyway, then there is no reason not to use cookies.

Furthermore, many websites rely on cookies. There are many sections of the Yahoo! and MSDN websites that you cannot visit without having cookies enabled. In other words, requiring visitors to have cookies enabled to use your website is not an entirely unreasonable requirement.

Creating Cookies

You create a new cookie by adding a cookie to the Response.Cookies collection. The Response.Cookies collection contains all the cookies sent from the web server to the web browser.

For example, the page in Listing 22.1 enables you to create a new cookie named Message. The page contains a form that enables you to enter the value of the Message cookie (see Figure 22.1).

Figure 22.1. Creating a new cookie.


Listing 22.1. SetCookie.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs)         Response.Cookies("message").Value = txtCookieValue.Text     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Set Cookie</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Text="Cookie Value:"         AssociatedControl         Runat="server" />     <asp:TextBox                  Runat="server" />     <asp:Button                  Text="Add Value"         OnClick="btnAdd_Click"         Runat="server" />     </div>     </form> </body> </html> 

Be warned that cookie names are case sensitive. Setting a cookie named message is different from setting a cookie named Message.

If you want to modify the value of the cookie created by the page in Listing 22.1, then you can open the page and enter a new value for the message cookie. When the web server sends its response to the browser, the modified value of the cookie is set on the browser.

The page in Listing 22.1 creates a session cookie. The cookie disappears when you close your web browser. If you want to create a persistent cookie, then you need to specify an expiration date for the cookie.

The page in Listing 22.2 creates a persistent cookie.

Listing 22.2. SetPersistentCookie.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Private Sub Page_Load()         ' Get current value of cookie         Dim counter As Integer = 0         If Not IsNothing(Request.Cookies("counter")) Then             counter = Int32.Parse(Request.Cookies("counter").Value)         End If         ' Increment counter         counter = counter + 1         ' Add persistent cookie to browser         Response.Cookies("counter").Value = counter.ToString()         Response.Cookies("counter").Expires = DateTime.Now.AddYears(2)         ' Display value of counter cookie         lblCounter.Text = counter.ToString()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Set Persistent Cookie</title> </head> <body>     <form  runat="server">     <div>     You have visited this page     <asp:Label                  Runat="server" />     times!     </div>     </form> </body> </html> 

The page in Listing 22.2 tracks the number of times that you have requested the page. A persistent cookie named counter is used to track page requests. Notice that the counter cookie's Expires property is set to two years in the future. When you set a particular expiration date for a cookie, the cookie is stored as a persistent cookie.

Reading Cookies

You use the Response.Cookies collection to create and modify cookies. You use the Request.Cookies collection to retrieve a cookie's value.

For example, the page in Listing 22.3 retrieves the message cookie's value.

Listing 22.3. GetCookie.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         If Not IsNothing(Request.Cookies("message")) Then             lblCookieValue.Text = Request.Cookies("message").Value         End If     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Get Cookie</title> </head> <body>     <form  runat="server">     <div>     The value of the message cookie is:     <asp:Label                  Runat="server" />     </div>     </form> </body> </html> 

In Listing 22.3, the IsNothing() function is used to check whether the cookie exists before reading its value. If you don't include this check, you might get a null reference exception. Also, don't forget that cookie names are case sensitive.

The page in Listing 22.4 lists all cookies contained in the Request.Cookies collection (see Figure 22.2).

Figure 22.2. Displaying a list of all cookies.


Listing 22.4. GetAllCookies.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         Dim colCookies As New ArrayList()         For i As Integer = 0 To Request.Cookies.Count - 1             colCookies.Add(Request.Cookies(i))         Next         grdCookies.DataSource = colCookies         grdCookies.DataBind()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Get All Cookies</title> </head> <body>     <form  runat="server">     <div>     <asp:GridView                  Runat="server"/>     </div>     </form> </body> </html> 

Notice that the only meaningful information that you get back from iterating through the Request.Cookies collection is the HasKeys, Name, and Value properties. The other columns show incorrect information. For example, the Expires column always displays a minimal date. Browsers don't communicate these additional properties with page requests, so you can't retrieve these property values.

When using the Request.Cookies collection, it is important to understand that a For...Each loop returns different values than a For...Next loop. If you iterate through the Request.Cookies collection with a For...Each loop, you get the cookie names. If you iterate through the collection with a For...Next loop, then you get instances of the HttpCookie class (described in the next section).

Setting Cookie Properties

Cookies are represented with the HttpCookie class. When you create or read a cookie, you can use any of the properties of this class:

  • Domain Enables you to specify the domain associated with the cookie. The default value is the current domain.

  • Expires Enables you to create a persistent cookie by specifying an expiration date.

  • HasKeys Enables you to determine whether a cookie is a multi-valued cookie (see the section "Working with Multi-Valued Cookies" later in this chapter).

  • HttpOnly Enables you to prevent a cookie from being accessed by JavaScript.

  • Name Enables you to specify a name for a cookie.

  • Path Enables you to specify the path associated with a cookie. The default value is /.

  • Secure Enables you to require a cookie to be transmitted across a Secure Sockets Layer (SSL) connection.

  • Value Enables you to get or set a cookie value.

  • Values Enables you to get or set a particular value when working with a multi-valued cookie (see the section "Working with Multi-Valued Cookies" later in this chapter).

A couple of these properties require additional explanation. For example, you might find the Domain property confusing because you can't change the domain associated with a cookie.

The Domain property is useful when your organization includes subdomains. If you want to set a cookie that can be read by the Sales.MyCompany.com, Managers.MyCompany.com, and Support.MyCompany.com domains, then you can set the Domain property to the value .MyCompany.com (notice the leading period). You can't, however, use this property to associate a cookie with an entirely different domain.

The HttpOnly property enables you to specify whether a cookie can be accessed from JavaScript code. This property works only with Internet Explorer 6 (Service Pack 1) and above. The property was introduced to help prevent cross-site scripting attacks.

The Path property enables you to scope cookies to a particular path. For example, if you are hosting multiple applications in the same domain, and you do not want the applications to share the same cookies, then you can use the Path property to prevent one application from reading another application's cookies.

The Path property sounds really useful. Unfortunately, you should never use it. Internet Explorer performs a case-sensitive match against the path. If a user uses a different case when typing the path to a page into the address bar, then the cookie isn't sent. In other words, the following two paths don't match:

http://localhost/original/GetAllCookies.aspx http://localhost/ORIGINAL/GetAllCookies.aspx 


Deleting Cookies

The method for deleting cookies is not intuitive. To delete an existing cookie, you must set its expiration date to a date in the past.

The page in Listing 22.5 illustrates how you can delete a single cookie. The page contains a form field for the cookie name. When you submit the form, the cookie with the specified name is deleted.

Listing 22.5. DeleteCookie.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub btnDelete_Click(ByVal sender As Object, ByVal e As EventArgs)         Response.Cookies(txtCookieName.Text).Expires = DateTime.Now.AddDays(-1)     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Delete Cookie</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Text="Cookie Name:"         AssociatedControl         Runat="server" />     <asp:TextBox                  Runat="server" />     <asp:Button                  Text="Delete Cookie"         OnClick="btnDelete_Click"         Runat="server" />     </div>     </form> </body> </html> 

The particular date that you specify when deleting a cookie doesn't really matter as long as it is in the past. In Listing 22.5, the expiration date is set to one day ago.

The page in Listing 22.6 deletes all cookies sent from the browser to the current domain (and path).

Listing 22.6. DeleteAllCookies.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         Dim cookies As String() = Request.Cookies.AllKeys         for each cookie As String in cookies             BulletedList1.Items.Add("Deleting " & cookie)             Response.Cookies(cookie).Expires = DateTime.Now.AddDays(-1)         Next     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Delete All Cookies</title> </head> <body>     <form  runat="server">     <div>     <h1>Delete All Cookies</h1>     <asp:BulletedList                  EnableViewState="false"         Runat="server" />     </div>     </form> </body> </html> 

The page in Listing 22.6 loops through all the cookie names from the Request.Cookies collection and deletes each cookie.

Working with Multi-Valued Cookies

According to the cookie specifications, browsers should not store more than 20 cookies from a single domain. You can work around this limitation by creating multi-valued cookies.

A multi-valued cookie is a single cookie that contains subkeys. You can create as many subkeys as you need.

For example, the page in Listing 22.7 creates a multi-valued cookie named preferences. The preferences cookie is used to store a first name, last name, and favorite color (see Figure 22.3).

Figure 22.3. Creating a multi-valued cookie.


Listing 22.7. SetCookieValues.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub btnSubmit_Click(ByVal s As Object, ByVal e As EventArgs)         Response.Cookies("preferences")("firstName") = txtFirstName.Text         Response.Cookies("preferences")("lastName") = txtLastName.Text         Response.Cookies("preferences")("favoriteColor") = txtFavoriteColor.Text         Response.Cookies("preferences").Expires = DateTime.MaxValue     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Set Cookie Values</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Text="First Name:"         AssociatedControl         Runat="server" />     <br />     <asp:TextBox                  Runat="server" />     <br /><br />     <asp:Label                  Text="Last Name:"         AssociatedControl         Runat="server" />     <br />     <asp:TextBox                  Runat="server" />     <br /><br />     <asp:Label                  Text="Favorite Color:"         AssociatedControl         Runat="server" />     <br />     <asp:TextBox                  Runat="server" />     <br /><br />     <asp:Button                  Text="Submit"         OnClick="btnSubmit_Click"         Runat="server" />     </div>     </form> </body> </html> 

When you submit the page in Listing 22.7, the following HTTP header is sent to the browser:

Set-Cookie: preferences=firstName=Steve&lastName=Walther&favoriteColor=green; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/ 


The page in Listing 22.8 reads the values from the preferences cookie.

Listing 22.8. GetCookieValues.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">     Sub Page_Load()         If Not IsNothing(Request.Cookies("preferences")) Then             lblFirstName.Text = Request.Cookies("preferences")("firstName")             lblLastName.Text = Request.Cookies("preferences")("lastName")             lblFavoriteColor.Text = Request.Cookies("preferences")("favoriteColor")         End If     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Get Cookie Values</title> </head> <body>     <form  runat="server">     <div>     First Name:     <asp:Label                  Runat="server" />     <br />     Last Name:     <asp:Label                  Runat="server" />     <br />     Favorite Color:     <asp:Label                  Runat="server" />     </div>     </form> </body> </html> 

You can use the HttpCookie.HasKeys property to detect whether a cookie is a normal cookie or a multi-valued cookie.




ASP. NET 2.0 Unleashed
ASP.NET 2.0 Unleashed
ISBN: 0672328232
EAN: 2147483647
Year: 2006
Pages: 276

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net