Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,128 | Comments: 45,550

filter by tags archive

Rhino SecurityPart II - Discussing the Implementation

time to read 7 min | 1205 words

I just finished testing an annoying but important feature, NHibernate's second level cache integration with Rhino Security. The security rules are a natural candidate for caching, since they change to change on an infrequent basis but are queried often. As such, it is obvious why I spent time ensuring that the whole thing works successfully.

At any rate, what I wanted to talk about today was structure of the framework. You can see the table layout below.

A few things to note:

  • The tables are all in the "security" schema, I find that it makes more sense this way, but you can set it to work with "security_Operation" if you really like (or the DB doesn't support schemas).
  • User is referenced a few times, but is not shown here. As I mentioned earlier, the user entity is an external concept. We are using the mapping rewriting technique that we discussed earlier.

(more below)


Here is the main interface for Rhino Security:


The tasks it performs are:

  • Enhance a query with security information.
  • Get an explanation about why permission was given / denied.
  • Perform an explicit permission check on entity or feature.

The last two are fairly easy to understand, but what does the last one means? It means that if I want to perform a "select * from accounts" and I enhance the query, I will give this baby:

SELECT THIS_.ID          AS ID4_0_,


       THIS_.NAME        AS NAME4_0_




                       INNER JOIN SECURITY_OPERATIONS OP1_

                         ON THIS_0_.OPERATION = OP1_.ID


                         ON THIS_0_.ENTITIESGROUP = ENTITYGROU2_.ID


                         ON ENTITYGROU2_.ID = ENTITIES7_.GROUPID



              WHERE    OP1_.NAME IN (@p1,@p2)

                       AND (THIS_0_."User" = @p3

                             OR THIS_0_.USERSGROUP IN (@p4))



                             OR (THIS_0_.ENTITYSECURITYKEY IS NULL

                                 AND THIS_0_.ENTITIESGROUP IS NULL))

              ORDER BY THIS_0_.LEVEL DESC,

                       THIS_0_.ALLOW ASC);

Isn't it cute?  This is much better than some home grown security system that I have seen (some of which I have built, actually), since it is stable with regards to the cost of the query that it will use. I mention before that it is possible to de-normalize the information into a single table, but since this requires more invasive approach from the application side, and since I have not seen performance issues with this yet, I'll leave it at this point for the moment.

Advance: Working with non DB backed users

In most applications, the user is a fully fledged entity, even if your authentication is elsewhere. Just keeping things like preferences will necessitate that, but let us assume that we really have that as a non DB entity.

In this case, we would need to make modifications to the tables (which we generally do, anyway, although automatically), and re-map the user references as an IUserType that can get the user from an id instead of a foreign key to entity. I think I'll wait until someone really needs it to make a demo of it.

Anyway, this is the main magic. It was fairly hard to get it right, as a matter of fact. But the query enhancement was one of the things that made security a breeze in my last project. We had a custom security module, but many of the concepts are the same.

The next part we will talk a bit about the IsAllowed and how that works. There is some nice magic there as well.

More posts in "Rhino Security" series:

  1. (25 Jan 2008) External API
  2. (24 Jan 2008) Part II - Discussing the Implementation


Peter F.

Ayende, could explain your vision of the EntityGroup a bit more? I quoted your previous comments on the concept but it's not clear to me what the purpose is.

"Permissions can be granted and revoked on an Entity Group, and those are applicable to all the entities that are member in this group. This way, business logic that touches permissions doesn't need to be scattered all over the place, when a state change affects the permissions on an entity, it is added or removed to an entity group, which has a well known operations defined on it."

-- Wouldn't an entity type have well-known operations defined on it already (i.e., Account.Edit)? And aren't the permissions just the set of privileges within the available operations?

"An Entity Group is a way to specify permissions for a set of entities, while the key is the set of permissions on a specific entity"

-- Are you intending the EntityGroup to be a security hierarchy? Is I create the AccountGroup with Account.View permission set on it, what is the affect on members of that entitygroup and why?

In my own acl security implementation I associated an entity with a default set of permissions that served for any requesting identity NOT in the acl entries table. Is that the point of the EntityGroup?

Also, what do you think about a rule extension point to the entry table for a contextual rule. This could be the Policy or set of policy rules which might be "Valid between 9am and 5pm M-F", and "If amount < 1000". The gates are:

  1. Can this user perform this operation

  2. Can this user perform this operation on this/these entities

  3. Can this user perform this operation on these entities under the current context.

I'm not sure how one would load up and execute such a rules engine for lists but it could be applied as a specification to filter out the returned entities.

Ayende Rahien


I'll answer about entities group in another post.

About adding rules as well, this is tricky, because how am I going make those kind of rules work in the database?

I can deal with most of those through the entities group, except the time based one, I am afraid.

Robert M.


Can you show us an example on how to configure Rhino.Security in a real world project (not test suites)?

I am particularly interested in how would you organize and setup

IEntityInformationExtractor classes for multiple domain objects and how would you initialize them in Windsor.boo?

Do I have to write "component IEntityInformationExtractor of Account, AccountInfromationExtractor" for each PONO that I have in my app and for which I want to apply security?



Ayende Rahien


I assume that most of the time, you have a layer super type for your project, so you can register a single one and let the container resolve it for each type, generically.


Can you show us an example on how to configure Rhino.Security in a real world project (not test suites)?

That would be great.. for example in your Hibernating.Forums sample .. if you add the securtiy layer and your ideas on some controller / entities / group of entities as a sample, i can send you patches for the details.

Ayende Rahien


Feel free to send them, I would love to see that.

Peter F.

Right, I don't think you could run a rules filter in the database (unless your rule could be expressed as SQL) but you could provide a filter in-memory that uses the association during the load process. I was thinking of something like:





and a one-to-many association between the permission entries table to the Policy table. The Policy is just a collection of rule specifications that can determine the requesting context and each entity that is built is intercepted like Filter(Policy.IsSatisfiedBy(entity));

Not sure that NHibernate could do this, but the larger question is whether a security layer can exist solely in the database. I think that's an interesting problem.

Comment preview

Comments have been closed on this topic.


  1. The worker pattern - about one day from now

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    26 May 2016 - The client side
  2. RavenDB 3.5 whirl wind tour (14):
    25 May 2016 - Got anything to declare, ya smuggler?
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats