Hi DJ,
Instance-level permissions are very powerful indeed, however, you don't want
to create hundreds or thousands of them. Typically my applications use a
mix of logic that requires knowledge of how the application works as well as
permission checks:
Based on your example, I would only check if someone is allowed to review an
entry if they are NOT the reviewer already assigned to the entry.
For example:
------------------
Subject currentSubject = SecurityUtils.getSubject();
User user = userDAO.findUser(currentSubject.getPrincipal());
if ( currentUser.equals(entry.getReviewer()) ||
currentSubject.isPermitted("entry:review:" + entry.getId() ) ) {
//allow them to review the entry
} else {
//don't allow - show them an error message?
}
------------------
This is an example of implied permissioning - where you allow the review,
because of your knowledge of the domain model - combined with explicit
permissioning (with actual JSecurity permission checks).
This improves performance in three immediately noticeable ways:
1) Due to Java's boolean 'short-circuiting', the JSecurity permission check
is never executed unless the current user is _not_ the one assigned directly
to it. In most applications, the permission check is not executed
frequently since the person 'assigned' to an entity is usually the one that
interacts with it the most.
2) When a JSecurity permission check *is* required, there are fewer
instance-level permissions to filter through. That is, if there are 10
permissions assigned to the user and or his roles, this is a faster check
than say, if there were 100 permissions to check through.
3) The lower the number of Permission instances in your RDBMS, the faster
the queries are when constituting a user's authorization state. Of course
this is mitigated by appropriate 2nd-level caching in a Hibernate/JPA
application too.
I hope that helps! Please let me know if you have more questions.
Cheers,
Les
On Mon, Jan 26, 2009 at 9:35 AM, Daniel J. Lauk <[email protected]>wrote:
> Hello, list.
>
> I am considering rewriting my app's instance level security code.
> Currently I use roles and evaluate certain fields on my objects for
> governing instance level access.
> I think, using permissions would help clean up the code a lot.
>
> Now my question is -- just to be sure:
> When I change the relationship of a user to a domain object, I'd have
> to change permissions as well, right?
>
> That means, put very abstract, that the code has to change like that:
>
> //old
> void changeReviewer(User aUser) {
> if (aUser == null)
> throw new BadParamException("aUser is null");
> this.setReviewer(aUser);
> }
>
> //new
> void changeReviewer(User aUser) {
> if (aUser == null)
> throw new BadParamException("aUser is null");
> User oldReviewer = this.getReviewer();
> Transaction t = new Transaction();
> try {
> this.setReviewer(aUser);
> permDao.delete("entry:review:" + this.id, oldReviewer);
> permDao.create("entry:review:" + this.id, aUser);
> t.commit();
> } catch (Exception e) {
> t.rollback();
> }
> }
>
> Is this correct or am I horribly over complicating things right now?
> I'm still not 100% sure about how to use permissions...
>
> Thanks in advance!
>
> Cheers,
> DJ
>