Rhino security with Unity

15 September 2009

If you are using NHibernate and need an integrated authorization framework, then have a look at Rhino Security. Rhino Security is a security framework developed by Ayende, creator of Rhino Mocks and the Nhibernate Profiler, among other things. 

Rhino Security automatically adds entities and services to your application for managing security. It provides the ability to decorate your own User entity with an IUser interface, making it suitable for use in authorization. There is the notion of user groups (Roles), operations, entities, entity groups and permissions. Authorization is done based on both operation and entity level. So you can define permissions for users and usergroups on operations, entities and even groups of entities.

It is amazingly flexible and even adds the ability to filter queries based on permissions. So for example, as a marketing manager, you only get to see the products you have permissions for.

For more information on how to use Rhino Security checkout:

- Ayendes blog: http://ayende.com/Blog/category/548.aspx

- Bart Reyserhove’s blog: http://bartreyserhove.blogspot.com/search/label/rhino%20security

Rhino security used to have dependencies on Castle Windsor and Rhino Tools, making it quite hard to use if you had already chosen another IOC container, like Unity for example. Luckily, in the latest version, Ayende has eliminated those dependencies and swapped them out for the Common Service Locator.

Common Service Locator

For those of you who are unfamiliar with the Common Service Locator, the Common Service Locator is a shared interface for IOC containers available on codeplex, which abstracts the specifics of IOC containers. The goal of this generic interface is to have frameworks only rely on this generic interface, making it possible for the users of the framework to plug in the IOC container they are using. So, because Rhino Security is now making use of this Common Service Locator, it is now possible to have it use our own Unity container, this way having better integration.

So, how do you use Rhino Security with Unity?

Using Rhino Security with Unity

First, get the latest version of Rhino Security from Github:

http://github.com/ayende/rhino-security

Next, get the latest version of the Unity adapter for the Common Service Locator from codeplex:

http://www.codeplex.com/CommonServiceLocator

Now what I did is write a Unity container extensions to provide the Rhino Security integration:

    /// <summary>
/// Custom extension that sets up the dependencies needed to use Rhino Security.
/// </summary>
    public class UnityRhinoSecurityExtension : UnityContainerExtension
{
protected override void Initialize()
{
// Setup dependencies needed by Rhino Security.
            Container.RegisterType<IAuthorizationService, AuthorizationService>();
Container.RegisterType<IAuthorizationRepository, AuthorizationRepository>();
Container.RegisterType<IPermissionsBuilderService, PermissionsBuilderService>();
Container.RegisterType<IPermissionsService, PermissionsService>();

        </span><span style="color:#008000;">//</span><span style="color:#008000;"> Make our Nhibernate Session available to Rhino Security.</span><span style="color:#008000;">

Container.AddNewExtension<StaticFactoryExtension>();

        Container.Configure</span><span style="color:#000000;">&lt;</span><span style="color:#000000;">IStaticFactoryConfiguration</span><span style="color:#000000;">&gt;</span><span style="color:#000000;">()
            .RegisterFactory</span><span style="color:#000000;">&lt;</span><span style="color:#000000;">ISession</span><span style="color:#000000;">&gt;</span><span style="color:#000000;">(GetSession);

        </span><span style="color:#008000;">//</span><span style="color:#008000;"> Indicate that Rhino Security should use our Unity container for looking up dependencies.</span><span style="color:#008000;">

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container)); }

    </span><span style="color:#0000FF;">private</span><span style="color:#000000;"> </span><span style="color:#0000FF;">static</span><span style="color:#000000;"> ISession GetSession(IUnityContainer container)
    {
        </span><span style="color:#0000FF;">return</span><span style="color:#000000;"> container.Resolve</span><span style="color:#000000;">&lt;</span><span style="color:#000000;">ISessionManager</span><span style="color:#000000;">&gt;</span><span style="color:#000000;">().Session;
    }
}</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

In the GetSession method you have to return the instance of the Nhibernate Session you are using. After this, add the extension to your container:

container.AddNewExtension<UnityRhinoSecurityExtension>();

The following line in the extension configures the Common Service Locator to use the Unity adapter and passes the instance of the container we are using:

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));

Now the only thing left to do, is to give Rhino Security access to our Nhibernate configuration, so It can add the mappings for its own entities. We are using Fluent Nhibernate, which makes our configuration look like the following:

return Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2005.
                  ConnectionString(
                  x => x.FromConnectionStringWithKey(ConnectionStringConfigKey))
                  .ProxyFactoryFactory(typeof (ProxyFactoryFactory).AssemblyQualifiedName))
    .Mappings(m => m.AutoMappings.Add(AutoPersistenceModel.MapEntitiesFromAssemblyOf<User>()))
    .ExposeConfiguration(cfg => Security.Configure<User>(cfg, SecurityTableStructure.Prefix))
    .BuildSessionFactory();

The following line exposes our configuration to Rhino Security:

.ExposeConfiguration(cfg => Security.Configure<User>(cfg, SecurityTableStructure.Prefix))

Now when you generate the database schema from you Nhibernate configuration, you are able to use the Rhino Security services to implement authorization in you application.