Unity and AOP: Cross-Cutting Security Functionality

With the release of Unity 2.0, a dependency injection container, the team at Altoros explored how to implement the capabilities of aspect-oriented programming with the help of the framework. In this post, we demonstrate how the paradigm works on the example of cross-cutting security functionality injection.
Challenge
In our example, there is a set of repositories that we can access from domain objects—Employees, Orders, and Devices. These objects are placed in different types of storage—Active Directory, external ERP, or a locally stored XML file accordingly. Each repository has different underlying storage, so it is difficult to control user permissions. In our case, we also enable only users with admin roles to perform the create/edit/delete operations for domain objects, while all the other users are limited to the read operations
Performing key operations for domain objects in a repositoryWith the help of NUnit, we have formulated these requirements in the following unit tests.
1. Users with the admin role have the Save functionality access. We also ran the same test for Delete.
[Test]
public void CheckThatAdminHaveSaveAccess()
{
// init
Thread.CurrentPrincipal = new Principal("Admin");
// action
var result = employeeRepository.Save(new List<Employee>() {<span>new <span>Employee()});
// assert
Assert.AreEqual(result, 1);
}
2. Users with the user role do not have the Save functionality access (the same for Delete).
[Test]
[ExpectedException(typeof(MethodAccessSecurityException))]
public void CheckThatUserHaveNotSaveAccess()
{
// init
Thread.CurrentPrincipal = new Principal("User");
// action
var result = employeeRepository.Save(new List<Employee>() {new Employee()});
// assert
Assert.AreEqual(result, 1);
}
3. Users with the user role have the Get functionality access (the same for the admin role).
[Test]
public void CheckThatUserHaveGetAccess()
{
// init
Thread.CurrentPrincipal = new Principal("User");
// action
var result = employeeRepository.Get();
// assert
Assert.AreNotEqual(result.Count, 0);
}
The performed unit tests work for each type of the repositories mentioned above.
How Unity can help
With cross-cut functionality injection, Unity provides possibility to intercept method calls by using call handlers (e.g., the ICallHandler interface). This interface includes the invokemethod, which contains required functionality that should be executed before actual method execution. In our example, it will be permission to check functionality. In addition, this interface defines the Orders property, which should return the call handler order number. This is useful in case of using several call handlers (we can specify the order of their execution).
The Unity interception process (Image credit)After having our custom call handlers implemented, we should specify when and where they should be executed. Unity allows for several ways to do it. With the attribute approach, we should mark methods with custom attributes inherited from HandlerAttribute. These attributes are responsible for appropriate call handler creation by overriding the CreateHandler factory method.
Step 1
First of all, we will create a call handler that should contain permission check logic.
public class MethodAccessCallHandler : ICallHandler
{
private readonly string[] roles;
public MethodAccessCallHandler(params string[] roles)
{
this.roles = roles;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate
getNext)
{
IPrincipal principal = Thread.CurrentPrincipal;
bool allowed = roles.Any(principal.IsInRole);
if (!allowed)
return input.CreateExceptionMethodReturn(new
Exceptions.MethodAccessSecurityException());
return getNext()(input, getNext);
}
public int Order { get; set; }
}
Our call handler throws MethodAccessSecurityException, a custom exception inherited from ApplicationException, in case of a permission check failure.
Step 2
After that, we will create a custom attribute inherited from HandlerAttribute that should override the CreateHandler factory method for the appropriate call handler creation (see Step 1).
public class MethodAccessAttribute : HandlerAttribute
{
private readonly string[] roles;
public MethodAccessAttribute(params string[] roles)
{
this.roles = roles;
}
public override ICallHandler CreateHandler(IUnityContainer container)
{
return newMethodAccessCallHandler(roles);
}
}
Step 3
Then, we will mark the IRepository interface methods (permission to which should be controlled) with the attribute created during Step 2.
public interface IRepository
{
[MethodAccess(Roles.AdminRole, Roles.UserRole)]
IList<T> Get();
[MethodAccess(Roles.AdminRole)]
int Save(IList<T> entities);
[MethodAccess(Roles.AdminRole)]
int Delete(IList<Guid> ids);
}
By marking these methods, we actually add permission check functionality to all classes that will implement this interface. Now, you can run unit tests.
Unity allows us to inject cross-cutting functionality with minimal efforts across such areas as domain object changes tracking, automatic PropertyChanged event rising for all domain object properties, etc.
About the author
Further reading
- How to Run Capybara Tests for Ruby Applications in Remote Browsers
- Speeding up Ruby Tests
- Linq-To-Sql: Alternative to the ‘WHERE IN’ Expression
This blog post was written by Aliaksei Yenzhyieuski; edited by Olga Belokurdkaya and Alex Khizhniak.



