Examining ASP.NET's Membership, Roles, and Profile - Part 12By Scott Mitchell
Several of the earlier installments in this article series examined how to apply authorization rules in order to prohibit particular users, roles, or classes of users from accessing particular resources. For instance, Part 2 showed how to define URL-based authorization rules in
web.configfor roles. With just a bit of XML markup, it is possible to block particular users or roles from visiting certain web pages. Just installments also looked at using the LoginView control, which displays different markup based on whether the user is authenticated or not (and can also be used to display different markup based on the currently logged in user's role). There are also programmatic techniques you can use to determine the identity of the currently logged on user and what roles she belongs to.
The URL-based authorization, LoginView control, and programmatic techniques can be used in tandem to ensure that a user does not visit a page or
perform some operation if she is not authorized. But what if you forget to implement one of these safeguards? For example, imagine that you have a web
page that includes a button that, when clicked, perform some task that is only intended for administrators. You could put this button in a LoginView
control or you could use programmatic techniques to ensure that only users in the appropriate role (say,
Admin) saw the button. But what if
sometime later you, or another developer, removed this check by accident? The net result would be that any user visiting the page could perform the
administrator-only operation! Whoops!
To reduce the likelihood of such security mishaps, the .NET Framework includes capabilities for declaratively asserting permissions (via attributes) on methods and classes. In a nutshell, you can add such attributes to ASP.NET pages, their code-behind classes, and your business logic and data access layers. With these attributes in place, your visitors will be barred from performing unauthorized actions, regardless of whether there are any security holes in the user interface. Read on to learn more!
PrincipalPermissionAttribute Class to Declaratively Define Authorization Rules
The .NET Framework includes a class named
PrincipalPermissionAttributethat enables developers to apply principal permissions to code using declarative syntax. This attribute can decorate either classes or methods and its properties spell out what users or roles can access the class or method it decorates. The
PrincipalPermissionAttributeclass has the following important properties:
Action- defines the authorization check that is to be performed. There are a number of different
Actionoptions. The one you'll use most often is
Demand, which requires that all callers in the call stack have the permission specified by the other properties.
Authenticated- a Boolean value that indicates whether the caller must be authenticated or not.
Name- the name of the caller. An ASP.NET web application this is typically the username of the currently logged in user.
Role- the name of the role the caller must belong to.
Actionproperty is mandatory, but the other ones can be used in various combinations. For example, to declare that a particular method can only be accessed by users in a particular role, you would use the following syntax:
PrincipalPermissionAttribute class is located in the
System.Security.Permissions namespace. You may need to
import this namespace into the class files or ASP.net pages that use the
You can also combine the
Role properties in a single attribute declaration.
Doing so requires that the caller have all security permissions outlined. For example, to require that the user have the name Scott and along
to the role Admin, use the following:
To allow access for a caller that satisfies one or more conditions use multiple
PrincipalPermissionAttributes. For instance,
the following declarations grant access to the method if the caller is user Scott or is in the role Admin:
Declaratively Applying Authorization Rules to Methods
The code available for download at the end of this article includes a simple business logic layer implemented as a single class named
App_Codefolder. This class has three dummy methods:
SomeAdminAction- a method meant only to be called by users in the
SomeAuthenticatedAction- a method meant only to be called by authenticated users
SomeActionForScottOrSam- a method meant only to be called by users Scott or Sam
PrincipalPermissionAttributes to each method. The following code implements these attributes and ensures that the methods can only be executed by those users or roles that have permission.
These attributes can also be added to methods and event handlers in the code-behind classes of ASP.NET web pages.
Declaratively Applying Authorization Rules to Classes
In addition to protecting particular methods, you can use
PrincipalPermissionAttributeto protect an entire class. Simply add the attribute immediately above the class declaration. The demo for download at the end of this article uses this functionality to prohibit anonymous users from visiting the
WhoIsOnline.aspxpage. This is accomplished by adding a
PrincipalPermissionAttributeattribute to the class declaration in the page's code-behind file:
What Happens When a Declarative Security Violation Occurs?
If an unauthorized caller executes a method or evokes a class that is decorated with a
SecurityExceptionexception is thrown. If there is no error handling the exception will bubble up to the ASP.NET runtime and will be handled there. Depending on how your website is configured this may display the "yellow screen of death" (see the following screenshot) or a custom error page.
This exception can be gracefully handled in a number of ways. You can surround the call to the protected methods and classes with a
performing some action in the event of a
SecurityException. The following code snippet and screenshot are from the code available for download
at the end of this article, and show a simple
Try...Catch block implementation. Specifically, if a
SecurityException is raised
SomeActionForScottOrSam a message is displayed in a Label control (
the website available for download from the end of this article has three user accounts: Scott, Jisun, and Sam. If Jisun logs on to the site,
visits the page
~/UsersOnly/Default.aspx, and clicks the button "Perform some operation that only Scott and Sam can do" the above
code is executed. The
SomeActionForScottOrSam method includes two
PrincipalPermissionAttribute attributes that permit only
users Scott and Sam. Consequently, when Jisun calls this method a
SecurityException is thrown. The appropriate
Catch block executes, displaying
the message shown in the screenshot below.
Another option is to automatically redirect users to a particular web page in the event of a security exception. This can be accomplished by creating an event handler
for the application's
Error event in
Error event is raised whenever an unhandled exception bubbles up to the ASP.NET
runtime. Here we can determine what type of exception was raised and take action based on that knowledge. The following event handler redirects the user
to a page named
Unauthorized.aspx whenever an unhandled
SecurityException percolates up to the ASP.NET runtime.
With this event handler in place in the event of an unauthorized access the caller is automatically shown the following screen.
|Use the |
Keep in mind that the purpose of the |
If you download the demo at the end of this article you will no doubt notice the lack of preemptive checks in the presentation layer.
For instance, there are buttons to perform actions that are only available to authenticated users, yet these buttons are displayed to both
authenticated and anonymous users. Likewise, there are buttons to perform actions are only available to users in the Admin role, yet these buttons
are shown to all, regardless of their role. This design was done purposefully so as to illustrate the behavior of the
A well-designed website automatically prohibits users from visiting pages they are not authorized to see and hides user interface elements that perform actions that the currently logged on user cannot perform. However, it is easy to overlook a particular user interface element and accidentally show it to all users even though it performs an action that's reserved for a few. It's good practice to decorate your methods and classes with appropriate
PrincipalPermissionAttributeattributes. These attributes provide a declarative means for defining what callers can access what classes and methods, and serves as a final check in case there are security holes or oversights in the presentation layer.