I did look at the code however it was too simple for my needs. The
system I developed has 10's of thousands of users and 1000's of
permissions and managing them as Strings would be difficult as would
be creating Roles or Groups for every possible combination. One
scenario might be as follows:
1. Users have permission across the system such as the ability to use
IM or email
2. Users can join projects dynamically by signing up or being invited.
3. Project owners control capabilities within the projects for all
users for example one project might allow IM or not deny it if the
user already has that capability and another project might not allow
any users to IM even if they have it at a higher level. Once a deny
is hit the permission is denied but if it is not allowed or is allowed
and not denied the permission is allowed. The query never goes lower
than the requesting level.
This is where the deny capability becomes important. It would be
prohibitive to assign the IM capability to each user in each project
as they sign up and the data would grow too large to query
efficiently. For legal reasons I might want to deny capability to IM
for a project for even those that have it across the system.
The most efficient way I have found to do this is to grant the IM
capability at the highest level and then if required (very seldom) use
a deny to make sure no one can IM from a project. The hierarchy I am
dealing with is much more complex than this with potentially 10 levels
of permission hierarchy but the idea still holds true. In the past I
have done this in LDAP and bit masks to get the performance i needed
but am trying to implement in Shiro to test it out in a new grails
application.
Scott Ryan
[email protected]
On Aug 31, 2009, at 11:44 AM, Les Hazlewood wrote:
Hi Scott,
The samples/spring and samples/spring-hibernate examples both provide
these in the BootstrapDataPopulator beans. The Spring/Hibernate
sample uses JPA annotations to specify these tables/mappings.
On Mon, Aug 31, 2009 at 12:41 PM, Scott Ryan<[email protected]>
wrote:
Has anyone published a sample implementation of a permission scheme
with
tables and code? There is a fairly complex example for other
security
frameworks including heirarchical roles and bit based permissioning.
You're right, there aren't any more complicated examples beyond the
existing samples because groups/roles/permissions modeling is _very_
environment/application specific - everyone does it their own way.
Shiro's primary focus has been on creating a security framework that
is powerful and flexible enough to work with any application, and not
necessarily on recommending data models to support application
frameworks.
But that's not to say what you're asking isn't valuable. A decent
number of people have asked for similar things. I think I'll have to
come up with a reasonable complex data model that could support most
deployments (sticking to the 80/20 rule - I'm sure there are 20%
fringe cases which I wouldn't model).
But let's talk about your specific needs here, and hopefully it will
give you ideas how to use Shiro to support them.
Also how to handle denies? I assume that denies encountered while
scanning from user to manager to admin should be enforced
Your Realm implementation supports grant vs deny logic in the
isPermitted or hasRole methods - it is up to you exactly what happens.
Most people go with a grant-only policy for simplicity. A Subject
would never never have permissions to do anything unless the
isPermitted implementation returns true for a particular user.
Note that most of Shiro's default Realm implementations extend
AuthorizingRealm and do these checks for you automatically, but for
more complicated enterprise applications, you'll probably want to
implement or override all of those checks yourself to delegate to an
internal data model.
I have a need to have multiple levels of permissions with the
ability to
allow or deny permissions at any level and to support inheritance.
For example I may have a heirarchy of roles:
Admin
Manager
User
I personally don't like to do this - it makes the data model
unnecessarily complex IMO. To me, a role is nothing more than a named
set of permissions. Multiple roles may or may not overlap their
permissions set, and I write my application to automatically assign
whatever roles necessary depending on the type of user.
For example, if in a UI, I create a new 'admin' user, then my code
would automatically assign all 3 roles to the user to achieve your
desired effect:
Role adminRole = getRole("admin");
Role managerRole = getRole("manager");
Role userRole = getRole("user");
user.addRole(userRole);
user.addRole(managerRole);
user.addRole(adminRole);
When you don't model things this way, you have to go through the major
headache of grant vs deny problems - "I've assigned all these
permissions to this particular role, but in this one case, I want to
remove permission X for this particular child role/user".
Ouch - very difficult to manage in code and a major frustration. Your
head starts to spin with inclusion/exclusion policies.
Its far better to ignore exclusionary policies and just assign
permissions to roles and assign roles to users and/or groups. I
personally don't have any recommendations about 'denies' - my systems
are always grant-based specifically to avoid the many problems and
large confusion arising from exclusionary policies.
My general rule of thumb:
A Role is a named Set of permissons
a User 'has' a Set of one or more Roles
a User 'has' a Set of permissions for that-user-only permissions (not
shared with anyone else - otherwise they'd go in a Role)
A Group is a named Set of 'Party' objects (a User is a Party and a
Group is a Party - allowing for instances of both to exist in
hierarchical Party trees)
If anyone has any other ideas, I'd love to hear them. Especially if
you've had to deal with exclusionary policies and how you made that
work in Shiro. I personally have avoided that like the plague ;)
Regards,
Les