what data should I store in the FormsAuthentication Ticket?
开发者_C百科I need to store a list of user's friends so I can use it in every page (without the need to make a database query every time).
I thought about SessionState
but I think this is gonna be heavy, since the database is huge.
So I need to know if using FormsAuthenticationTicket
is the right way to do it? Or should I use HttpOnly
Cookies too?
FormsAuthenticationTicket
You can store custom data in a FormsAuthenticationTicket in the following manner:
string userData = "john smith;jane doe;bill murray";
HttpCookie cookie = FormsAuthentication.GetAuthCookie(user.UserName, true);
// Get the FormsAuthenticationTicket out of the encrypted cookie
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
// Create a new FormsAuthenticationTicket that includes the custom user data
var newTicket = new FormsAuthenticationTicket(ticket.Version,
ticket.Name,
ticket.IssueDate,
ticket.Expiration,
true,
userData);
However I would be very carefull about what kind of data you include in the cookie. There are security issues for one thing and if you store too much data in it then you risk creating an invalid cookie. Plus cookies are sent to the server on each request. This will only increase the size of the request.
IIRC there is a 4KB size limit (maximum cookie size). So the amount of data which you can store in the cookie is certainly limited. And because the forms authentication cookie already contains data besides the user data and is encrypted your available storage limit is even lower.
I would only use it for very small pieces of information that I need upon each request. Certainly not data that can grow such as a list of friends. Rather identifiers, that I can use on the server to look something up. Even when the cookie is decryped these values are meaningless.
Session State
I would not store such data on the user's pc. This way this data will be distributed accross every PC / browser that he uses. If you want to avoid database roundtrips, then this would be a prime candidate for caching.
Honestly, I would store the list of friends in the session state. When the logger logs in, retrieve the list of friends once and store it in the session. When the list of friends is updated, just update the session data. Each subsequenct request can then retrieve the user's list of friends from the session state.
But apparently you don't want to store it in the session? Might be a good time to investigate if your session state provider can be changed. For example using an AppFabric cache cluster to store the session state. This way it scales more easily than the default InProc or StateServer modes.
You could give the data an expiration of an hour for example. After this timeout the list of friends is invalidated and no longer available in the session. You need to retrieve an (updated) list from the database once more. However, this way you only execute a query once every hour.
But surely storing a simple list of friends in the session state cannot not be that big of a problem. What else are you storing in it? Surely not the entire database.
You can try to store into the Cache object with SqlDependency.
For example, you are caching the result of following query (it is a simple one, I'm sure SqlDependecy would like it) and also you can create the friends "graph" from it.
select u.UserId, u.FirstName, u.LastName, f.FriendId
from Users u
left join Friends f on f.UserId = u.UserId
If you are changing the friends list, delete an user, etc, then the cache is invalidated and you don't need to worry from where you change it, from a separate application like an admin/cms or from Management Studio.
So, basically you are having a single graph of friends in the Application memory which is accessed very fast by every user from theirs sessions.
Managing the data from a cookie can be very hard to do, actually I can't image how you will be sure that the list of the friends from a cookie is the same as the one in the database.
精彩评论