Implementing Role-Based Security with ASP.NETBy Darren Neimke
|A More Up-To-Date Article is Available!|
|A more up-to-date article on role-based authentication is available. Check out: Role-Based Authorization with Forms Authentication.|
|Forms Authentication with ASP.NET|
This article is a follow up to Darren's earlier article, Using Forms Authentication in ASP.NET.
In this previous article, Darren examines how to use ASP.NET's built-in forms authentication to authenticate
users. This article demonstrates how to restrict (or grant) access to users based on their roles, and serves
as a complement to Darren's previous article.
This article also contains a fully working sample application. You can download this sample application and try out the Role Security features on your own Web server.
In my previous article, I demonstrated how authentication providers can be used to manage the process of authenticating users. I also showed that classes and methods exist within the .NET Framework that can be used to inspect the basic attributes of a current user. In this article, I will extend upon that base, by showing how the .NET Framework provides support for the implementation of role based security.
Before we start, let's take a quick look at what roles are, and how they might be commonly used within an application. Imagine for a moment that you have been assigned the task of converting an online forum from Classic ASP to ASP.NET. One of the hurdles that you are likely to face lies in determining the identities of the users, and then granting access to certain features based on who that user is and what "role" they play within the application.
As you begin to form a picture of what roles are required, you might find that you end up with four basic "classes" of user:
- System Administrator - this class of user can perform any task - add/delete posts and forums, ban users, approved messages posted to moderated forums, etc.
- Moderator - this user can only approve messages that were posted to moderated forums.
- Subscriber - these are users that are registered and authorized to post new messages, but are restricted from all administrative areas of the site.
- Other/Public - these users merely have permission to browse to public pages within the site and read-only access to forum posts.
If you've come straight out of developing classic ASP applications, your first instinct may be to maintain user state in the Session object, and, then do some type of database lookup for an associated UserType to establish the role of the user. (In fact a previous 4Guys article, Logins and Permissions, demonstrates how to accomplish this "role"-based authorization using Session variables in classic ASP.)
Typically, classic ASP applications relied heavily on this type of model, involving repeated database lookups to retrieve role based information.
With ASP.NET, however, this model changes. Before examining how roles are handled in ASP.NET, let's first translate the classic ASP Session-based code from above into VB.NET code that would appear in our ASP.NET Web page:
Although the above code probably doesn't mean much to you yet, it will by the time we've finished. Essentially,
you can see that we interrogate a
User object to extract the role information.
But what is this
User object?, And how does it get the role information?, I hear you asking.
Principals, Roles, and Identities, Oh My!
If you've done any administering of Windows you will be familiar with the concept of Users and Groups. Basically, to access a secured network you must have a user account and that account would be assigned to one or many groups. In .NET these are referred to as Identities and Roles respectively, and they are contained within a
Principal object. To understand how role based authorization works you need to have an
understanding of how these three elements are tied together, and how you can programmatically access their
values. Let's look at each element separately.
Identities represent users, and as such, have properties that allow you to obtain information (such as the username) about that user.
The classes for working with Identities reside in the
Namespace. This namespace contains two classes:
through which you can determine the properties of a user; and one interface:
IIdentity that you
can use to create custom Identities that can extend the base Identity type to suit needs that are specific to your application.
Roles are simply a comma-delimited String of role names that are added to the Principal to associate the current user with a role/s.
A Principal contains information about the identity and role/s that the current user is associated with. It is through the Principal that you are able to check the role membership of the current user. In many ways a Principal is the glue that binds identities, roles, and the various other pieces of information that fully describe that Principal to the application.
A Principal is encapsulated by classes
found in the
System.Security.Principal Namespace. This namespace contains two Classes:
WindowsPrincipal through which you can determine the properties
of a principal; and one interface
IPrincipal that you can use to define your own custom Principals.
The .NET runtime uses the Principal that is attached to the current thread to gain information about the
identity and roles of a user when handling requests that require authorization.
To programmatically assign your own principal settings you simply create an instance of the
class passing in an identity object and a comma delimited string of roles for that identity. The constructor
Principal object looks like this:
Therefore at the time of authentication you might do something like this to add an authenticated user to a principal, assign it some roles, and attach it to the current thread.
In Part 2 we'll look at how to create your own roles. Once we've created these custom roles, we'll look at how to allow or deny certain methods or actions based on the authenticated user's role.