I\'ve been noticing static classes getting a lot of bad rep on SO in regards to being used to store global information. (And global variables being scorned upon in general)
Forget Singletons and static data. That pattern of access is going to fail you at some time.
Create your own custom IPrincipal and replace Thread.CurrentPrincipal with it at a point where login is appropriate. You typically keep the reference to the current IIdentity.
In your routine where the user logs on, e.g. you have verified their credentials, attach your custom principal to the Thread.
IIdentity currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
System.Threading.Thread.CurrentPrincipal
= new MyAppUser(1234,false,currentIdentity);
in ASP.Net you would also set the HttpContext.Current.User at the same time
public class MyAppUser : IPrincipal
{
private IIdentity _identity;
private UserId { get; private set; }
private IsAdmin { get; private set; } // perhaps use IsInRole
MyAppUser(userId, isAdmin, iIdentity)
{
if( iIdentity == null )
throw new ArgumentNullException("iIdentity");
UserId = userId;
IsAdmin = isAdmin;
_identity = iIdentity;
}
#region IPrincipal Members
public System.Security.Principal.IIdentity Identity
{
get { return _identity; }
}
// typically this stores a list of roles,
// but this conforms with the OP question
public bool IsInRole(string role)
{
if( "Admin".Equals(role) )
return IsAdmin;
throw new ArgumentException("Role " + role + " is not supported");
}
#endregion
}
This is the preferred way to do it, and it's in the framework for a reason. This way you can get at the user in a standard way.
We also do things like add properties if the user is anonymous (unknown) to support a scenario of mixed anonymous/logged-in authentication scenarios.
Additionally: