asp.net Cookie overview
Cookies provide a way to store user-specific information in a WEB application. For example, when a user accesses your site, you can use cookies to store user preferences or other information. When the user accesses your Web site again, the application can retrieve previously stored information.
What is a Cookie?
A Cookie is a small piece of textual information that accompanies the user request and the page is passed between the WEB server and the browser. Cookies contain information that the WEB application can read every time a user accesses the site.
For example, when a user requests a page in a Web, the application sends the user more than one page and a cookie containing the date and time, and the user's browser obtains the cookie and stores it in a folder on the user's hard disk.
Later, if the user requests a page in your site again, when the user enters a URL, the browser looks for the Cookie associated with the URL on the local hard disk. If the cookie exists, the browser sends the cookie to your site along with the page request. The application can then determine the date and time that the user last visited the site. You can use this information to display a message to the user or to check the expiration date.
Cookies are associated with a Web site, not with a particular page. Therefore, the browser and the server Exchange Cookie information regardless of which page in the site the user is requesting. When users visit different sites, each site may send a cookie to the user's browser, and the browser stores all cookies separately.
Cookies Help the Web site store information about visitors. In general, cookies are a way of keeping WEB application continuity (that is, performing state management). The browser is disconnected from the WEB server, except for a short period of actual exchange of information. For each request that a user makes to a Web server, the Web server handles it separately. However, in many cases, it is useful for a WEB server to identify users when they request a page. For example, a Web server on a shopping site tracks every shopper so that the site can manage shopping carts and other user-specific information. As a result, cookies can serve as a business card that provides relevant identification information to help the application determine how to proceed.
Cookies can be used for a variety of purposes, all of which are designed to help the site remember users. For example, a site that implements a poll can simply use the Cookie as a Boolean value to indicate whether the user's browser has participated in the vote, so that the user cannot vote for the second time. A site that requires a user to log on can use a Cookie to record that the user is logged in, so that the user does not have to enter credentials each time.
Limitations of cookies
Most browsers support cookies with a maximum of 4096 bytes. Because this limits the size of cookies, it is best to use cookies to store small amounts of data, or to store identifiers such as user IDs. The user ID can then be used to identify the user and to read user information from a database or other data source. (For information on storing security recommendations for user information, see the "Cookies and Security" section below.) )
Browsers also limit the number of cookies that a site can store on a user's computer. Most browsers allow only 20 cookies per site, and if you try to store more cookies, the oldest cookies are discarded. Some browsers also have an absolute limit of the total number of cookies they will accept from all sites, usually 300.
The cookie limit you may encounter is that users can set their browser to reject cookies. If you define a P3P privacy policy and place it in the root directory of your Web site, more browsers will accept cookies from your site. However, you may have to completely discard cookies and use other mechanisms to store user-specific information. A common way to store user information is session state, but session state depends on cookies, as described in the "Cookie and Session State" section later.
Attention
For more information about state management in WEB applications and options for saving information, see ASP.net State management overview and ASP.net state Management recommendations.
Although cookies are useful in applications, applications should not rely on the ability to store cookies. Do not use cookies to support critical functionality. If your application must rely on cookies, you can test to determine whether the browser will accept cookies. See the "Check whether the browser accepts cookies" section later in this topic.
Writing cookies
The browser is responsible for managing cookies on the user's system. The Cookie is sent to the browser through the HttpResponse object, which exposes a collection of called Cookies. You can access the HttpResponse object as the Response property of the Page class. All cookies to be sent to the browser must be added to this collection. When creating cookies, you need to specify Name and Value. Each cookie must have a unique name so that it can be recognized later when the cookie is read from the browser. Because cookies are stored by name, naming two cookies with the same name causes one of the cookies to be overwritten.
You can also set the expiration date and time for the Cookie. When a user accesses a site that writes cookies, the browser deletes the expired cookie. The validity of the cookie should be set to this time as long as the application considers the cookie value to be valid. For cookies that never expire, the expiration date can be set to 50 years from now.
Attention
Users can purge cookies on their computers at any time. Even if the stored cookie is a long time from the expiration date, the user can still decide to remove all cookies and clear all the settings stored in the cookie.
If you do not set the expiration date for a cookie, a cookie is still created, but it is not stored on the user's hard disk. The Cookie is maintained as part of the user's session information. When the user closes the browser, the Cookie is discarded. This non-persistent Cookie is ideal for storing information that is stored only for a short time, or for storing information that should not be written to a disk on the client computer for security reasons. For example, if a user is using a public computer and you do not want to write cookies to the computer's disk, you can use a non-persistent cookie.
You can add cookies to a collection of cookies in a variety of ways. The following example shows two ways of writing cookies:
Copy Code code as follows:
response.cookies["UserName"]. Value = "Patrick";
response.cookies["UserName"]. Expires = DateTime.Now.AddDays (1);
HttpCookie acookie = new HttpCookie ("lastvisit");
Acookie.value = DateTime.Now.ToString ();
Acookie.expires = DateTime.Now.AddDays (1);
RESPONSE.COOKIES.ADD (Acookie);
This example adds two cookies to the cookie collection, one named UserName and the other named Lastvisit. The value for the first Cookie,cookies collection is set directly. You can add values to the collection in this way, because Cookies are derived from a private collection of nameobjectcollectionbase types.
For the second Cookie, the code creates an object instance of the HttpCookie type, sets its properties, and then adds it to the cookie collection through the Add method. When instantiating a HttpCookie object, the name of the Cookie must be passed as part of the constructor.
Both examples complete the same task by writing a Cookie to the browser. In both of these methods, the expiration value must be a DateTime type. However, lastvisited values are also date-time values. Because all Cookie values are stored as strings, the date time value must be converted to string.
Multi-Value Cookies
You can store a value in a Cookie, such as the user name and the last access time. You can also store multiple name/value pairs in a Cookie. Name/value pairs are called child keys. (a subkey layout is similar to a query string in a URL.) For example, instead of creating two separate cookies named UserName and lastvisit, you can create a cookie named UserInfo that contains two subkeys UserName and lastvisit.
You may use subkeys for a variety of reasons. First, it is convenient to put relevant or similar information in a Cookie. In addition, because all information is in a cookie, the cookie attribute such as the expiration date applies to all information. (Conversely, if you want to specify different expiration dates for different types of information, you should store the information in a separate Cookie.) )
Cookies with subkeys can also help you limit the size of your cookie file. As mentioned in the previous "Cookie Limit" section, cookies are typically limited to 4096 bytes, and each site can store up to 20 cookies. Using a single cookie with a key, the number of cookies used will not exceed the 20 limit assigned to the site. In addition, a Cookie consumes about 50 characters of system overhead (for saving the expiration information, and so on), plus the length of the value stored in it, and the sum is close to 4096 bytes. If you store five subkeys instead of five separate cookies, you can save the system overhead of a separate cookie and save about 200 bytes.
To create a cookie with a key, you can use a variety of syntax for writing a single cookie. The following example shows two methods for writing the same cookie with two subkeys per cookie:
Copy Code code as follows:
response.cookies["UserInfo" ["userName"] = "Patrick";
response.cookies["UserInfo" ["lastvisit"] = DateTime.Now.ToString ();
response.cookies["UserInfo"]. Expires = DateTime.Now.AddDays (1);
HttpCookie acookie = new HttpCookie ("UserInfo");
acookie.values["userName"] = "Patrick";
acookie.values["lastvisit"] = DateTime.Now.ToString ();
Acookie.expires = DateTime.Now.AddDays (1);
RESPONSE.COOKIES.ADD (Acookie);
Controlling the range of cookies
By default, all cookies for a site are stored together on the client, and all cookies are sent to the server along with any requests sent to that site. That is, every page in a site can get all the cookies for that site. However, you can set the range of cookies in two ways:
Restrict the scope of the cookie to a folder on the server, which allows you to restrict cookies to an application on the site.
Setting the scope to a domain allows you to specify which subdomains in the domain can access cookies.
Restricting cookies to a folder or application
To restrict cookies to a folder on the server, set the Path property for the cookie by following the example:
Copy Code code as follows:
HttpCookie Appcookie = new HttpCookie ("Appcookie");
Appcookie.value = "written" + DateTime.Now.ToString ();
Appcookie.expires = DateTime.Now.AddDays (1);
Appcookie.path = "/application1";
RESPONSE.COOKIES.ADD (Appcookie);
Attention
You can also write cookies by adding cookies directly to the collection of cookies, as shown in the previous example.
The path can be either a physical path under the site root or a virtual root directory. The effect is that cookies can only be used in Application1 folders or pages in the virtual root directory. For example, if your site name is http://www.contoso.com/, the Cookie that you created in the previous example will be available only for paths http://www.contoso.com/Application1/ Page and all of the pages under that folder. However, cookies will not be available for pages in other applications, such as http://www.contoso.com/Application2/or http://www.contoso.com/.
Attention
In some browsers, paths are case-sensitive. You cannot control how users type a URL in their browser, but if the application relies on a Cookie that is related to a particular path, make sure that the URL in all the hyperlinks you create matches the case of the Path property value.
Limit the domain scope of a Cookie
By default, a Cookie is associated with a specific domain. For example, if your site is http://www.contoso.com/, the cookies you write will be sent to the server when a user requests any pages from that site. (This may not include cookies with a specific path value.) If the site has a child domain (for example, contoso.com, sales.contoso.com, and support.contoso.com), you can associate a Cookie with a specific subdomain. To do this, set the Domain property of the Cookie, as shown in the example:
response.cookies["Domain". Value = DateTime.Now.ToString ();
response.cookies["Domain". Expires = DateTime.Now.AddDays (1);
response.cookies["Domain". Domain = "support.contoso.com";
When you set a field in this manner, the Cookie is available only for pages in the specified child domain. You can also use the Domain property to create cookies that can be shared across multiple subdomains, as shown in the following example:
Copy Code code as follows:
response.cookies["Domain". Value = DateTime.Now.ToString ();
response.cookies["Domain". Expires = DateTime.Now.AddDays (1);
response.cookies["Domain". Domain = "contoso.com";
Cookies will then be available for the primary domain or for the sales.contoso.com and support.contoso.com domains.
Read cookies
When the browser makes a request to the server, it sends the server's cookies along with the request. In an ASP.net application, you can use the HttpRequest object to read the Cookie, which is used as the Request property of the Page class. The structure of the HttpRequest object is essentially the same as the structure of the HttpResponse object, so the cookie can be read from the HttpRequest object and read in the same way that the cookie was written to the HttpResponse object. The following code example shows two ways in which you can get the value of a Cookie named username and display its value in a Label control:
Copy Code code as follows:
if (request.cookies["userName"]!= null)
Label1.Text = Server.HTMLEncode (request.cookies["UserName"). Value);
if (request.cookies["userName"]!= null)
{
HttpCookie acookie = request.cookies["UserName"];
Label1.Text = Server.HTMLEncode (Acookie.value);
}
You should ensure that the cookie exists before attempting to get the value of the cookie, and you will receive a NullReferenceException exception if the cookie does not exist. Also, notice that the HtmlEncode method encodes the contents of the cookie before displaying the contents of the cookie in the page. This ensures that the malicious user does not add executable script to the Cookie. For more information about cookie security, see the "Cookies and Security" section.
Attention
Because different browsers store cookies differently, it is not necessary for different browsers on the same computer to be able to read each other's cookies. For example, if you use Internet Explorer to test a page and then test it with another browser, the latter will not find cookies saved by Internet Explorer.
The method of reading the neutron key value of a Cookie is similar to the method for setting the value. The following code example shows one way to get a child key value:
Copy Code code as follows:
if (request.cookies["UserInfo"]!= null)
{
Label1.Text =
Server.HTMLEncode (request.cookies["UserInfo"] ["userName"]);
Label2.Text =
Server.HTMLEncode (request.cookies["UserInfo"] ["lastvisit"]);
}
In the above example, the code reads the value of the subkey Lastvisit, which was previously set to a DateTime value in the string representation. Cookies store values as strings, so if you want to use the Lastvisit value as a date, you must convert it to the appropriate type, as shown in the example:
DateTime DT;
DT = DateTime.Parse (request.cookies["UserInfo"] ["lastvisit"]);
A subkey in a Cookie is typed as a collection of namevaluecollection types. Therefore, another way to get a single subkey is to get a set of subkeys and then extract the subkey values by name, as shown in the following example:
Copy Code code as follows:
if (request.cookies["UserInfo"]!= null)
{
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection;
UserInfoCookieCollection = request.cookies["UserInfo"]. Values;
Label1.Text =
Server.HTMLEncode (userinfocookiecollection["UserName"]);
Label2.Text =
Server.HTMLEncode (userinfocookiecollection["lastvisit"]);
}
Change the expiration date of a Cookie
The browser is responsible for managing cookies, and the expiration time and date of a cookie can help the browser manage the storage of cookies. Therefore, although the name and value of the cookie can be read, the expiration date and time of the cookie cannot be read. The expiration information is not included when the browser sends Cookie information to the server. (The Expires property of the Cookie always returns a DateTime value with a value of 0.) If you are concerned about the expiration date of the cookie, you must reset the cookie, which is described in the "Modifying and deleting Cookies" section.
Attention
You can read the Expires property of a cookie that has been set in the HttpResponse object before sending a cookie to the browser. However, you cannot get the expiration date from the returned HttpRequest object.
Read Cookie Collection
Sometimes, you may need to read all the cookies available to the page. To read the names and values of all the cookies available to the page, you can use the following code to go through the cookie collection.
Copy Code code as follows:
System.Text.StringBuilder output = new System.Text.StringBuilder ();
HttpCookie Acookie;
for (int i=0; i<request.cookies.count; i++)
{
Acookie = Request.cookies[i];
Output. Append ("Cookie name =" + Server.HTMLEncode (acookie.name)
+ "<br/>");
Output. Append ("Cookie value =" + Server.HTMLEncode (acookie.value)
+ "<br/><br/>");
}
Label1.Text = output. ToString ();
Attention
When you run this code, you may see a Cookie named Asp.net_sessionid. ASP.net uses this Cookie to store a unique identifier for your session. The session Cookie is not saved on your hard disk. For more information about session cookies, see the "Cookie and Session State" section later in this topic.
The above example has a limit: if the Cookie has a subkey, the subkey is displayed with a name/value string. You can read the HasKeys property of the cookie to determine whether the cookie has subkeys. If so, you can read the subkeys collection to get individual subkey names and values. You can read a child key value directly from the Values collection by index value. The corresponding subkey name can be obtained in the AllKeys member of the Values collection, and the member returns an array of strings. You can also use the Keys members of the Values collection. However, the property is cached the first time the AllKeys property is accessed. By contrast, this property generates an array each time the Keys property is accessed. Therefore, within the context of the same page request, the AllKeys property is much faster when accessed later.
The following example shows a modification to the previous example. The example uses the HasKeys property to test for the existence of a subkey, and if a subkey is detected, gets the subkey from the Values collection:
Copy Code code as follows:
for (int i=0; i<request.cookies.count; i++)
{
Acookie = Request.cookies[i];
Output. Append ("Name =" + acookie.name + "<br/>");
if (Acookie.haskeys)
{
for (int j=0; j<acookie.values.count; j + +)
{
SubkeyName = Server.HTMLEncode (Acookie.values.allkeys[j]);
Subkeyvalue = Server.HTMLEncode (Acookie.values[j]);
Output. Append ("Subkey name =" + SubkeyName + "<br/>");
Output. Append ("Subkey value =" + Subkeyvalue +
"<br/><br/>");
}
}
Else
{
Output. Append ("Value =" + Server.HTMLEncode (acookie.value) +
"<br/><br/>");
}
}
Label1.Text = output. ToString ();
Alternatively, you can extract the subkey as a NameValueCollection object, as shown in the following example:
Copy Code code as follows:
System.Text.StringBuilder output = new System.Text.StringBuilder ();
HttpCookie Acookie;
String SubkeyName;
String Subkeyvalue;
for (int i = 0; i < Request.Cookies.Count; i++)
{
Acookie = Request.cookies[i];
Output. Append ("Name =" + acookie.name + "<br/>");
if (Acookie.haskeys)
{
System.Collections.Specialized.NameValueCollection cookievalues =
Acookie.values;
string[] Cookievaluenames = Cookievalues.allkeys;
for (int j = 0; J < Cookievalues.count; J + +)
{
SubkeyName = Server.HTMLEncode (Cookievaluenames[j]);
Subkeyvalue = Server.HTMLEncode (Cookievalues[j]);
Output. Append ("Subkey name =" + SubkeyName + "<br/>");
Output. Append ("Subkey value =" + Subkeyvalue +
"<br/><br/>");
}
}
Else
{
Output. Append ("Value =" + Server.HTMLEncode (acookie.value) +
"<br/><br/>");
}
}
Label1.Text = output. ToString ();
modifying and deleting cookies
Cookies cannot be modified directly. The process of changing a cookie involves creating a new cookie with a new value and then sending it to the browser to overwrite the old version cookie on the client. The following code example demonstrates how to change the value of a Cookie that stores the number of times a user accesses a site:
Copy Code code as follows:
int counter;
if (request.cookies["counter"] = = null)
Counter = 0;
Else
{
counter = Int. Parse (request.cookies["counter"). Value);
}
counter++;
response.cookies["Counter"]. Value = counter. ToString ();
response.cookies["Counter"]. Expires = DateTime.Now.AddDays (1);
Deleting cookies deletes cookies (that is, physically removing cookies from the user's hard disk) is a form of modifying cookies. Because the Cookie is on the user's computer, it cannot be removed directly. However, you can have your browser remove cookies for you. The technique is to create a new cookie with the same name as the cookie to be deleted and set the expiration date of the cookie to a date earlier than the current date. When the browser checks the expiration date of the cookie, the browser discards the cookie that is now expired. The following code example demonstrates a way to delete all available cookies in an application:
Copy Code code as follows:
HttpCookie Acookie;
String CookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
CookieName = Request.cookies[i]. Name;
Acookie = new HttpCookie (cookiename);
Acookie.expires = DateTime.Now.AddDays (-1);
RESPONSE.COOKIES.ADD (Acookie);
}
Modifying or deleting a subkey modifies a single subkey in the same way as it was created, as shown in the following example:
response.cookies["UserInfo" ["lastvisit"] = DateTime.Now.ToString ();
response.cookies["UserInfo"]. Expires = DateTime.Now.AddDays (1);
To delete a single subkey, you can manipulate the Values collection of cookies, which are used to hold the subkeys. First, recreate the cookie by getting a cookie from the Cookies object. You can then call the Remove method of the Values collection, passing the name of the subkey that you want to delete to the Remove method. Next, add cookies to the cookie collection so that the cookie is sent back to the browser in the modified format. The following code example shows how to delete a child key. In this example, the name of the subkey to remove is specified in the variable.
Copy Code code as follows:
String SubkeyName;
SubkeyName = "UserName";
HttpCookie acookie = request.cookies["UserInfo"];
ACookie.Values.Remove (SubkeyName);
Acookie.expires = DateTime.Now.AddDays (1);
RESPONSE.COOKIES.ADD (Acookie);
Cookies and security
The security issue with cookies is similar to the security issue of getting data from the client. In an application, cookies are another form of user input, and are therefore easily exploited and illegally acquired by them. Because cookies are saved on the user's own computer, the user can at least see the data that you have stored in the cookie. The user can also change the cookie before the browser sends you a cookie.
Never store sensitive information in cookies, such as user name, password, credit card number, and so on. Do not place any content in the cookie that should not be available to the user, nor any content that may be controlled by someone else who steals cookies.
Also, don't be credulous of the information you get from cookies. Do not assume that the data is the same as when you write it, and that the security measures used when handling Cookie values should be the same as those used to handle data typed by users in the Web page. The example earlier in this topic shows how to HTML-encode the contents of a Cookie before displaying a value in the page, which is the same as before displaying any information obtained from a user.
Cookies are sent in clear text between browsers and servers, and anyone who can intercept WEB traffic can read cookies. You can set the cookie property to allow cookies to be transmitted only on connections that use Secure Sockets Layer (SSL). SSL does not prevent cookies that are stored on the user's computer from being read or manipulated, but prevents the cookie from being read during transmission because the cookie is encrypted. For more information, see Basic Security implementation policies for WEB applications.
Determine if the browser accepts cookies
Users can set their browser to refuse to accept cookies. No error is raised when a Cookie cannot be written. Similarly, the browser does not send any information about its current Cookie settings to the server.
Attention
The Cookies property does not indicate whether the Cookie is enabled. It only indicates whether the current browser originally supports cookies.
One way to determine whether a cookie is accepted is to try to write a cookie and then try to read the cookie again. If you cannot read cookies that you write, you can assume that the browser does not accept cookies.
The following code example shows how to test whether the browser accepts cookies. This sample consists of two pages. The first page writes out the Cookie, and then redirects the browser to the second page. The second page attempts to read the Cookie. The browser is then redirected back to the first page and the query string variable with the test result is added to the URL.
The code for the first page looks like this:
Copy Code code as follows:
protected void Page_Load (object sender, EventArgs e)
{
if (! Page.IsPostBack)
{
if (request.querystring["acceptscookies"] = = null)
{
response.cookies["TestCookie"]. Value = "OK";
response.cookies["TestCookie"]. Expires =
DateTime.Now.AddMinutes (1);
Response.Redirect ("testforcookies.aspx?redirect=" +
Server.URLEncode (Request.Url.ToString ()));
}
Else
{
Label1.Text = "Accept cookies =" +
Server.URLEncode (
request.querystring["AcceptsCookies"]);
}
}
}
The page tests first to determine if it is a postback, and if not, finds the query string variable name acceptscookies that contains the test results. If no query string variable exists, the test is not complete, so the code writes a Cookie named TestCookie. After writing out the Cookie, the example calls Redirect to switch to the TestForCookies.aspx test page. The information attached to the test page URL is a query string variable named redirect that contains the URL of the current page, so that it can be redirected back to this page after the test is executed.
A test page can consist entirely of code, and you do not need to include the control. The following code example illustrates the test page.
Copy Code code as follows:
protected void Page_Load (object sender, EventArgs e)
{
String redirect = request.querystring["redirect"];
String acceptscookies;
if (request.cookies["TestCookie"] ==null)
AcceptsCookies = "No";
Else
{
AcceptsCookies = "Yes";
Delete Test Cookie.
response.cookies["TestCookie"]. Expires =
DateTime.Now.AddDays (-1);
}
Response.Redirect (Redirect + "?) Acceptscookies= "+ acceptscookies,
true);
}
After reading the redirected query string variable, the code attempts to read the Cookie. For administrative purposes, if the Cookie exists, delete it immediately. After the test is complete, the code constructs a new URL by redirect the URL that is passed to it by the query string variable. The new URL also includes a query string variable that contains the test results. The final step is to redirect the browser to the original page using the new URL.
An improvement in the example is that you can save the Cookie test results to a persistent store, such as a database, so that you do not have to repeat the test every time the user views the original page. (By default, storing test results in session state requires cookies.) )
Cookies and Session state
When a user navigates to your site, the server establishes a unique session for that user, and the session continues until the user's access ends. ASP.net maintains session-state information for each session, and applications can store user-specific information in session-state information. For more information, see Session-State overview topics.
ASP.net must track the session ID of each user so that users can be mapped to session-state information on the server. By default, ASP.net uses a non-permanent Cookie to store session state. However, if the user has disabled cookies on the browser, session-state information cannot be stored in the cookie.
asp.net provides no Cookie session as an alternative. You can configure an application to not store a session ID in a Cookie and store it in the URL of a page in the site. If your application relies on session state, you can consider configuring it to use a no Cookie session. However, in fewer cases, if a user shares a URL with another person, possibly when the user sends the URL to a colleague and the user's session is still active, the two users may end up sharing the same session and the results will be unpredictable. For more information about configuring your application to use a Cookie-free session, see the ASP.net Status Management Overview topic.