The Role Manager


If you tried implementing role-based security with Forms authentication back in ASP.NET 1.x, you were pretty much on your own. Many people wrote code in global.asax to handle the Authorize event, replacing the IPrincipal implementation with a GenericPrincipal filled with a set of roles typically looked up in a database. But there were many others who didn't know enough about the Forms authentication mechanism to implement this, and those who did often weren't happy with the performance implications of hitting the database to look up roles for every single authenticated request.[14]

[14] See www.pluralsight.com/articlecontent/efficientRoleBasedAuthentication.pdf for a discussion of the issues involved.

Fortunately, ASP.NET 2.0 ships with a role manager and Role provider infrastructure that solves these problems. If you don't already have a role-based infrastructure, you can simply use the SqlRoleProvider that ships with ASP.NET. This class builds on the services provided by SqlMembershipProvider, allowing you to put users into roles that you can then use for authorizing requests.

The role database behind SqlRoleProvider is really straightforward. It simply adds a table of roles (aspnet_Roles) and a second table that links users to their roles (aspnet_UsersInRoles). The RoleProvider base class exposes the methods you'd expect, allowing you to create and delete roles, add and remove users from those roles, and check to see if a user is a member of a role. There's nothing surprising there.

If this were all the role infrastructure did, it would be really useful. But the ASP.NET team took this a bit further and provided an optional solution for the performance problem mentioned earlier. Their solution was to cache the roles for a user in an HTTP cookie. By caching these roles, the role manager doesn't have to hit the database for each request, since the cookie can be used to do a quick lookup instead. To prevent the cookie from being manipulated by a user who wants to modify her roles, the cookie is cryptographically protected with tamper detection and encryption by default. The user would need to learn the secret key stored on the Web server to be able to modify her cookie without being detected, which is the exact same protection that ASP.NET provides on the Forms login cookie by default.

Sophisticated applications can have lots of roles, which may not be feasible for storing in a cookie. To account for practical limitations on cookie size, the role manager has a configurable limit to the number of roles it'll cache in a cookie (maxCachedResults), which defaults to 25. While there was some talk early on about optimizing the use of this space by caching the most recently checked roles in the cookie, this code got too complicated for the ASP.NET team to manage and test properly, which is a really bad situation for a security feature. So in the released implementation, once the number of roles reaches this threshold, the cookie is simply cleared and not used at all.

Just as the Membership provider infrastructure comes with a Membership class, there is a Roles class that makes it easy to access roles. This class has a Provider property that lets you access the provider directly, although unlike the Membership class, the Roles class exposes 100 percent of the functionality of the underlying provider, which means you can use it exclusively without ever having to talk to the provider directly. The ASP.NET Administration Console sample that comes with this book is a good place to look for code that uses the Roles class, as it provides a Windows Forms interface for managing roles and member lists.

Once you've enabled the role manager, you can look up roles for the logged on user programmatically. The easiest way to do this is with the User property on your page or the HttpContext.User property. This refers to an instance of IPrincipal, and if you're using the role manager, the concrete class you'll see here will be RolePrincipal. So a simple call to User.IsInRole(string roleName) will tell you whether the logged-on user is in a particular role, or you can call RolePrincipal.GetRoles() to get an array of strings representing all the roles in which the user is a member. This latter technique is great for debugging, and don't forget about the LoginView control, which is a convenient way to display different content depending on the user's roles.




Essential ASP. NET 2.0
Essential ASP.NET 2.0
ISBN: 0321237706
EAN: 2147483647
Year: 2006
Pages: 104

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net