Q: I want to add extra data to the forms authentication cookie issued by FormsAuthentication.RedirectFromLoginPage. Is this possible, and if so, how? Do I need to derive from System.Web.Security.FormsAuthenticationTicket?
A: You unfortunately can't derive from FormsAuthenticationTicket because it's a sealed class. But you can use FormsAuthenticationTicket's UserData property to encode custom information in authentication cookies. An authentication cookie is nothing more than an HTTP cookie carrying an instance of FormsAuthenticationTicket as its payload.
The secret to storing user-defined data in forms authentication cookies is to modify the login page so that instead of issuing a normal authentication ticket, it issues one whose UserData property holds the extra data. That means replacing code like this:
FormsAuthentication.RedirectFromLoginPage (UserName, false);
with code like this:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket ( 1, // Version number UserName, // Username DateTime.Now, // Issue date DateTime.Now.AddMinutes (30), // Expiration date false, // Persistent? "Hello, world" // User data ); string eticket = FormsAuthentication.Encrypt (ticket); HttpCookie cookie = new HttpCookie (FormsAuthentication.FormsCookieName, eticket); Response.Cookies.Add (cookie); string url = FormsAuthentication.GetRedirectUrl (UserName, false); Response.Redirect (url);
The first statement creates an instance of FormsAuthenticationTicket containing the user's login name and other information normally found in an authentication ticket. It also initializes UserData with the string "Hello, world." Because UserData is a read-only property, setting it in FormsAuthenticationTicket's constructor is the only way to assign it a value.
The remaining statements transform the forms
authentication ticket into a forms authentication cookie. First,
FormsAuthentication.Encrypt is called to convert the ticket into a string as
well as possibly hashing and encrypting it. (Encrypt doesn't necessarily do any
hashing or encryption. Whether it hashes the ticket to prevent tampering or
encrypts the ticket's content to protect it from prying eyes - or both - is
controlled by the value of the protection attribute accompanying the
Once you've customized a forms authentication cookie with user data, you need to know how to read it back, too. The following code, which could appear in Global.asax or in an ASPX file, extracts the authentication ticket, if present, from the current request and reads its UserData property:
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity is FormsIdentity) { FormsAuthenticationTicket ticket = ((FormsIdentity) HttpContext.Current.User.Identity).Ticket; if (ticket != null) { string UserData = ticket.UserData; . . . } }
If forms authentication is being used, HttpContext.Current.User.Identity refers to an instance of FormsIdentity, whose Ticket property (of type FormsAuthenticationTicket) exposes the authentication ticket. Once the ticket is in hand, extracting the user-defined data contained within it is a simple matter of reading the ticket's UserData property.
A common use for UserData is to store a list of roles to which a user belongs when exercising role-based security. You can store anything you want in UserData, however, provided you can store it as a string. Convert.ToBase64String is a convenient mechanism for converting arbitrary binary data into text; use Convert.FromBase64String to reverse the process and recover the original data. Don't forget that the size restrictions browsers impose on cookie lengths (typically 4K) in turn limit the amount of data you can encode in UserData. Also, large UserData values decrease effective connection bandwidths by increasing the amount of information transmitted in each HTTP request.
Q: I'm using a tip from your last column to scroll a
DataGrid inside a A: The fundamental problem is that clicking on one of the
DataGrid's Edit buttons causes a postback to occur and returns brand-new HTML.
The solution is to inject some client-side script that tracks the scroll
position before a postback occurs and restores it afterward (see Figure 1). Figure 1. This page scrolls an editable DataGrid in a
region defined by a The sample I provided in my previous column uses a
DataGrid to display the products listed in the "Products" table of SQL Server's
Northwind database. The DataGrid includes a column of Edit buttons, and it
scrolls inside a region defined by a The other half of the equation is the C# code in the
<%...%> block. If the HTTP request includes a non-null __DIVPOS parameter
- that is, if the page is being fetched as a result of a postback - this
server-side script outputs client-side script that restores the pre-postback
position of the The code in this article is
available for download. Jeff Prosise is author of several books, including Programming Microsoft .NET
(Microsoft Press). He also is a co-founder of Wintellect (http://www.wintellect.com),
a software consulting and education firm that specializes in .NET. Got a
question for this column? Submit queries to [email protected]. Tell us what you think! Please send any comments about
this article to [email protected].
Please include the article title and author.<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%
if (Request["__DIVPOS"] != null &&
Request["__DIVPOS"] != String.Empty) {
int pos = Convert.ToInt32 (Request["__DIVPOS"]);
Response.Write ("\r\n");
}
%>
Figure 2. This DataGrid maintains its scroll position when an Edit
button is clicked on, despite the fact that the button click causes a postback.