Can I use Apache Shiro for a hierarchical user model?

957 Views Asked by At

I'm designing an application where users are organized in multiple levels hierarchies. Users can be assigned to any levels of this hierarchy with a role.

organization hierarchy example

So, I want to know if there is a way to adapt Apache Shiro to this hierarchies, where I can define permissions for roles IN organizations, it means, not just have an "admin" role which can do any action on any user, but an "admin" of the "organization A" which can do any actions on any users which belong to the "organization A" or any suborganizations of it.

I think what I'm looking for is a path mechanism, similar to the Apache Shiro wildcard system, but with paths to organizations, something like:

users:*:organizationA/*

This would mean a permission over users for any action over all the users within the organization A and all its suborganizations.

In the end, what I need is a permission system over resources in a hierarchical user model. Is there a way to model something like that with Apache Shiro? Should I use any other framework, or do I need to add some code to achieve this with Shiro?

2

There are 2 best solutions below

1
On

You can create subclass the WildcardPermission class and implement your own implies method to write your own implementation of a permission string.

Then override WildcardPermissionResolver to return your permission implementation instead of the standard one.

Then you can configure it to be used globally in shiro.ini:

globalPermissionResolver = com.foo.bar.MyPermissionResolver

See documentation here: https://shiro.apache.org/authorization.html#Authorization-Configuringaglobal%7B%7BPermissionResolver%7D%7D

0
On

Well, I ended up re-inventing the wheel. I discarded Apache Shiro as I couldn't find the usefulness of it if I had to implement my own permission resolver, so I created one myself. In my permission system I work with the organizations hierarchy which, by the way, ended up being a graph. As such, my permissions need to be a bit complex in their definition. This is how I composed them:

Role:ResourceType:Action:Scope

So the permissions are defined as: "This role, over this type of resources, can perform this action". And to relate that definition with the hierarchy, and therefore, to know how to use the role to resolve that, I have the scope. The scope tells us when the permission applies, and it is directly related to the hierarchy.

I'm assuming that I can place any resource in the hierarchy using a locator. A locator, in my case, is a user or an organization. I know this is quite complex (or perhaps it isn't and I'm just explaining it poorly), so let's jump to an example.

I have this hierarchy:

  • Organization: Camelot
    • king: arthur
    • knight: galahad
    • Organization: Round table
      • king: galahad
      • knight: lamorak

Now let's suppose we have a resource, Excalibur, of type mightyWeapon, and an action carry. Now, we want to tell this about mighty weapons: they can be carried by kings if they belong to the same organization or any other suborganizations. So our permission to tell so, would be this:

king:mightyWeapon:carry:sameBelow

The scope in this case is sameBelow that tells us this applies to the same organization the king belongs to or any suborganization of that organization.

Now, to check that, I have to tell where the resource is placed in the hierarchy. In this case, we assume Excalibur belongs to Camelot.

Let's now check if the user arthur can carry Excalibur. So, the variables involved in the resolution of the permission would be these:

  • User: arthur
  • Resource type: mightyWeapon
  • Action: carry
  • Locator of the resource: Camelot

Now, to resolve this permission check, we get all the membership records of arthur. That is, each organization he belongs to and the role applied. We have two:

  1. King of Camelot
  2. Knight of RoundTable

For each one, we try and resolve the permission. For the first one, we know kings can carry mighty weapons that belong to the same organization or any other below it. Excalibur belongs to Camelot, and so does arthur as King, so he can carry them. We will stop checking here, and the resolution of the permission would be possitive.

Now, let's check if galahad can carry Excalibur. He has these memberships:

  1. Knight of Camleot
  2. King of RoundTable

For the first one, we don't have any permission that tells us that Knights can carry mighty weapons, so we keep resolving.

For the second one, we know kings can carry mighty weapons, but Excalibur is not in the same level as galahad acting as king, or in any suborganization as that one, because RoundTable is itself a suborganization of Camelot. So, this permission check resolves as negative.

And that's it. I hope the example clarifies it a bit. Of course I have a bunch of scopes to make this more complete, but this was the best solution I came up with. Any suggestion to improve it is welcome.