Reputation: 101
I'm writing an ASP.NET MVC application and I'm using forms authentication with the default IPrincipal, IIDentity, etc.
In my authentication ticket I'm storing the username in the name parameter.
However, I'm running into instances where on every request my master layout needs access to not only the username, but also the email and userid of the user.
I need the email so I can load a gravitar icon for the user, the username so I can have a friendly display name in the top bar, and the userid so I can define certain links specific to that userid (ie, /users/edit/2332).
What is the cleanest way to store not just the username but also the userid and email?
Custom Principal/Identity objects? Cache? Session? Some other way?
Upvotes: 2
Views: 2364
Reputation: 15890
Use a custom IPrincipal
object with your own cookie management.
I would suggest serializing the custom IPrinicipal object to JSON and setting your cookie.UserData to the serialized string. That was it's easy to deserialize when the cookie comes back in.
EDIT: Example of a custom IPrincipal object and authentication cookie management
The IPrincipal
object (note I'm using Json.NET for serialization)
public class SimplePrincipal : IPrincipal
{
private IIdentity _identity;
[JsonIgnore]
public IIdentity Identity
{
get { return _identity ?? (_identity = new GenericIdentity(Name)); }
}
public string Name { get; set; }
public int WebUserId { get; set; }
public string Email { get; set; }
public long FacebookUserId { get; set; }
public IEnumerable<string> Roles { get; set; }
public bool IsInRole(string role)
{
return Roles.Contains(role);
}
/// <summary>
/// Get's a JSON serialized string of a SimplePrincipal object
/// </summary>
public static string GetCookieUserData(SimplePrincipal principal)
{
return JsonConvert.SerializeObject(principal);
}
/// <summary>
/// Creates a SimplePrincipal object using a JSON string from the asp.net auth cookie
/// </summary>
public static SimplePrincipal CreatePrincipalFromCookieData(string userData)
{
return JsonConvert.DeserializeObject<SimplePrincipal>(userData);
}
}
Login Method
private void LoginUser(SimplePrincipal principal, bool isPersistent)
{
var userData = SimplePrincipal.GetCookieUserData(principal);
var authCookie = FormsAuthService.GetAuthCookie(principal.Name, userData, isPersistent);
Response.Cookies.Add(authCookie);
}
Authentication Module
public class AuthModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.AuthenticateRequest += Application_AuthenticateRequest;
}
private void Application_AuthenticateRequest(Object source, EventArgs e)
{
var application = (HttpApplication)source;
var context = application.Context;
// Get the authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = context.Request.Cookies[cookieName];
if (authCookie == null)
return;
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
context.User = SimplePrincipal.CreatePrincipalFromCookieData(authTicket.UserData);
}
public void Dispose()
{
//Don't do anything
}
}
After all this is wired up correctly, you can simply get the object something like:
var principal = HttpContext.Current.User as SimplePrincipal
Upvotes: 6
Reputation: 76218
Use Session
if you want to keep it alive for the session (also the most straight forward approach). Use TempData
if you want to persist it between single requests (or until it is read out).
You can also use querystring or URL params but in this case, I wouldn't suggest it.
Do not use cache
as that is shared across all users of the site.
Ideally though, it should be a Custom Identity object
Upvotes: 0
Reputation: 593
I would suggest using Session object for storing this kind of information.
Upvotes: 0