Tags: , , | Categories: Articles, Tutorials Posted by RTomlinson on 9/3/2009 6:58 PM | Comments (10)

In Part 1 and Part 2 I covered how I went about building an authorization framework using Rhino Security. I am now going to cover how to integrate this into your domain model (business objects) and how we can use dynamic discovery for permission registration and database persistence.

In essence what I am saying here is that given the scenario whereby we have a domain object (lets use that of a Company business object, for example) we could state what available permissions that object could have. This post will therefore cover:

  • Defining permissions at an object level
  • The ability to register those permissions in the database

Defining Object Permissions

Having considered various implementations, I finally decided to go with an attribute based approach. The attribute requires the operation that you want access control over and to what level of granularity. For example, given the flexibility of the Rhino Security implementation we can use the operation convention of /BUSINESSOBJECT/OPERATION or /BUSINESSOBJECT/METHOD/OPERATION OR /BUSINESSOBJECT/PROPERTY/OPERATION.

In reality this would result in the following examples:

  • /Company/Add
  • /Company/Delete
  • /User/UserName/Set
As you can see this attribute (ACL) used below, it takes as a parameter, the operation and an enum that states what type of permission it is.

namespace MyApp.Core
{
    [ACL("/User/Add", "Restrict the ability to add new users", ACLType.ObjectLevel)]
    public class User : Entity, IUser
    {
        private IAuthorizationRepository _authRepo;
        protected User(IAuthorizationRepository authRepo) 
        {
            _authRepo = authRepo;
        }

        public User() 
        {
            _authRepo = ResolveType.Of<IAuthorizationRepository>();
        }

        [Length(6, 512)]
        [NotNullNotEmpty]
        public virtual string UserName { get; set; }

        [Length(6, 512)]
        [NotNullNotEmpty]
        public virtual string Password { get; set; }

 

Dynamic Permissions Discovery

Having created an attribute to apply the required information to an object we can use reflection to discover all of our permissions. Those permissions that have not been registered in the database can then be registered and any that no longer exist can be marked accordingly. The way that I implemented this was run this discovery in the Application_Start event of the Global.asax. Therefore whenever we start our application this process takes place and the overhead of some pretty heavy reflection is less of an issue.

This process, although sounding quote complex, is actually very very simple. I call a static Discover method that uses relflection to reflect the assembly, find those objects that the ACLAttribute has been applied to, checks whether that object is registered and if not then registers it.

public static void Discover(Castle.Windsor.IWindsorContainer Container)
{
  Assembly asm = Assembly.Load("MyApp.Core");

  Type[] types = asm.GetTypes();

  Type securityPermission = asm.GetType("MyApp.Core.Security.ACLAttribute", false);
  PropertyInfo operation = securityPermission.GetProperty("Operation");
  RegisterAssemblyTypes(Container, types, securityPermission, operation);
}

private static void RegisterAssemblyTypes(Castle.Windsor.IWindsorContainer Container, Type[] types, Type securityPermission, PropertyInfo operation)
{
  foreach (Type t in types)
  {
    object[] objs = t.GetCustomAttributes(securityPermission, false);

    foreach (object o in objs)
    {
      if (!Registered(operation.GetValue(o, null).ToString(), Container))
      {
        Register(operation.GetValue(o, null).ToString(), Container);
      }
    }
  }
}

This implementation works very well. It involves minimal work work the developer. When a new permission is required it simply means adding an attribute to the appropriate business object. This permission will then be automatically registered and will be visible within the permissions section of the application, allowing the administrator to associate a particular user with that permission to allow or deny the operation.

In the next post I will detail the how I implemented this using some nice jQuery iPhone checkboxes on top of the standard ASP.NET checkbox control.

blog comments powered by Disqus