Think twice about using RoleProvider
It’s a common misunderstanding that the RoleProvider in ASP.NET is the only means for populating a user’s roles in ASP.NET. The RoleProvider was introduced in ASP.NET 2.0, so prior to 2005 we did without.
In essence what’s needed to populate roles in ASP.NET is to have some code in the HTTP pipeline handle the PostAuthenticateRequest event and then load the roles for a user and populate the HttpContext.User and Thread.CurrentPrincipal properties in global.asax, as such:
void Application_PostAuthenticateRequest(object sender, EventArgs e) { var ctx = HttpContext.Current; if (ctx.Request.IsAuthenticated) { string[] roles = LookupRolesForUser(ctx.User.Identity.Name); var newUser = new GenericPrincipal(ctx.User.Identity, roles); ctx.User = Thread.CurrentPrincipal = newUser; } }
That wasn’t so bad.
So often people get pigeonholed into thinking they must use a RoleProvider because it’s some magical part of the infrastructure. In fact the RoleProvider is simply abstracting a database lookup. It has other APIs to manage roles (create roles, add/remove users to/from roles, etc.), but if all you need in your application is to load roles for the current user the RoleProvider might be too heavy weight for your needs.
Thanks man, it helped me a lot!
So, from the global.asax, how do you call a method? (LookupRolesForUser)
“LookupRolesForUser” is just some method you’d implement to accept the username and return an array of strings for the roles. Presumably it’s check whatever custom database you’ve developed to store the roles.
What I mean is where do I put the code? there is no .vb file for the global.asax – I see no ‘view code’ in the context menu
doah! – never mind
Works great – – wish I’d known this years ago
this is cool.
why do you not use one personel provider ? (herits providerrole ?)
I’m not sure I understand.
how can I access the roles I set up afterwards? When using Roles.GetRolesForUser() I keep getting an error with the RoleProviders on the roleManager (gotta have it set to “True” right?) on the webconfig. I’m going crazy over this
Isn’t enough to set ctx.User? Why you setting Thread.CurrentPrincipal as well?
You also have to set the thread’s principal because that’s where the rest of .NET looks for the user’s identity.
Worked For me !
Thanks :)
would this not be called on every request… ?
Yep, but this is the way it’s always been (as the same for the role manager/provider). So it’s a good idea to cache those roles somewhere.
Thanks for the tip. Saved me a lot of grief in implementing an entire RoleProvider.
See how i modified your wonderful method.. thanks a lot..
void Application_PostAuthenticateRequest()
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket authTicket;
if (authCookie == null || authCookie.Value == “”)
{
string[] roles = GetRolesStringArrayForUser(User.Identity.Name);
authTicket = new FormsAuthenticationTicket(
1, // version
User.Identity.Name, // user name
DateTime.Now, // created
DateTime.Now.AddMinutes(20), // expires
true, // persistent?
roles // can be used to store roles
);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Current.Response.Cookies.Add(authCookie);
}
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
string[] roles = authTicket.UserData.Split(‘;’);
if (Context.User != null)
Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
}
Using Authentication Mode=”Windows”, Application_PostAuthenticateRequest, and my custom Roles in SQL Server ?