When you authenticate a user within an ASP.NET application,
the authenticated user's identity will be automatically flowed throughout
that user's request on the server. What this means is that you don't need
to manually pass a user's identity around from method to method or class to
class. This makes it much easier to implement security authorization
rules throughout your application.
One little known feature in .NET is the ability to have the
CLR automatically use this identity information to authorize a user's capabilities
before instantiating a class, or accessing a method/property on it. This
makes it easy to add clean security authorization rules to your business and
data layers without having to write much code.
All you need to do to implement this is to use the
PrincipalPermissionAttribute within the "System.Security.Permissions"
namespace and decorate it on the appropriate class or member on it. For
example:
Listing 1
using System;
using System.Security.Permissions;
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
// todo
}
[PrincipalPermission(SecurityAction.Demand, Role = "HR")]
public void AddEmployee(Employee e)
{
// todo
}
}
In the above example, I have added a PrincipalPermission
attribute to the "EmployeeManager" class. By adding it I am
requiring that a user must be authenticated (logged-in) before this class can
be instantiated during a web request (the Authenticated=true demand enforces
this). I have also then added two additional security demands on the
"LookupEmployee" and "AddEmployee" methods. With the
LookupEmployee method I am requiring that the authenticated user for the
request is within the "Manager" role in order for the method to be
invoked. With the AddEmployee method I am requiring that the
authenticated user for the request is within the "HR" role in order
for this method to be invoked and have a new Employee added to the system.
And now if I accidentally introduce
a security hole within my UI tier and have some code-path that
allows a non-Manager/HR employee to cause these methods to be invoked, my
business tier will automatically prevent this from happening and raise a
security exception.
The PrincipalPermissionAttribute isn't tied to any specific
authentication mode. It will work with Forms Authentication, Windows
Authentication, Passport Authentication, or any custom authentication mode you
want to invent. It will also work with any Role implementation I might
use (so if you build or plug-in your own Role Provider in ASP.NET it will just
work).
The PrincipalPermissionAttribute type is implemented in the
standard CLR mscorlib assembly that all .NET projects compile against. So
it isn't ASP.NET specific, and can be used within any application type
(including Windows and Console applications). In addition to making it
more generically useful, this makes it easier to unit-test business/data
libraries built with it.