Hi folks
I am implementing asp.net 2.0 roles and authentication for the first time so bear with me if my ideas are a bit mixed-up!
I have written a CustomRoleProvider class which overrides all the necessary members required to use my custom datastore for user roles - and this appears to be working great. Next, I posted asking how to store extra information for my user as I require access to a userId (representing the primary key from my users table), companyId and company name (similar database columns).
I was advised to create a Custom Principal class (implementing the IPrincipal interface), and to add properties to this class to store the data I need, then on the Application_AuthenticateRequest event I initialise my CustomPrincipal object, sending in the data from the database. Here is the code:
CustomPrincipal.cs
public class CustomPrincipal : IPrincipal
{
#region "Private member variables"
private IIdentity _identity;
private int _userId;
private int _companyId;
private string _companyName;
#endregion
#region "Public member properties"
public IIdentity Identity
{
get
{
return _identity;
}
}
public int UserId
{
get
{
return _userId;
}
set
{
_userId = value;
}
}
public int CompanyId
{
get
{
return _companyId;
}
set
{
_companyId = value;
}
}
public string CompanyName
{
get
{
return _companyName;
}
set
{
_companyName = value;
}
}
#endregion
public CustomPrincipal(IIdentity identity, int userId, int companyId, string companyName)
{
_identity = identity;
_userId = userId;
_companyId = companyId;
_companyName = companyName;
}
// IPrincipal Implementation
public bool IsInRole(string role)
{
//How do I implement this?
return true;
}
}
Global.asax
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// Extract the forms authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null)
return;
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
if (authTicket == null)
return;
//Get extra user data from database
UserClass u = new UserClass(); //BLL object
int userId = 0;
int companyId = 0;
string companyName = string.Empty;
FormsIdentity id = new FormsIdentity(authTicket);
UserDataSet.UserDataTable users = u.GetUserByName(id.Name);
if (users.Rows.Count > 0)
{
UserDataSet.UserRow user = (UserDataSet.UserRow)users.Rows[0];
userId = user.UserID;
if (!user.IsCompanyIDNull())
{
companyId = user.CompanyID;
companyName = user.CompanyName;
}
}
// This principal will flow throughout the request.
CustomPrincipal principal = new CustomPrincipal(id, userId, companyId, companyName);
// Attach the new principal object to the current HttpContext object
Context.User = principal;
}
My questions are:
1. How do I implement the IsInRole(string role) method of the CustomPrincipal? Have I now made my CustomRolePovider redundant?
2. By getting the user data on every page load (which seems to be how often the Application_AuthenticateRequest event is fired) I am making an extra round-trip to the database. Is there a more efficient but equally secure way of persisting this data?
3. Finally, should I really be creating a custom Principal to hold the extra properties, or should it really be a custom Identity?
Sorry if this is a lengthy problem - I hope someone has the patience to read it!
Thanks in advance!