Actually Tamás, your solution is a very good one :) I'm glad you chimed in :)
The most important point of your example and my 2nd one is this: the solution is very application-specific and there's not much Shiro can do for the 'edit my own stuff' permission checks since it doesn't know your data model. In this case, the application would use a combination of the Shiro permission checks + data-model-specific association checks. Best, Les 2010/12/1 Tamás Cservenák <[email protected]>: > ... or, instead of that very complicated ( ;) ) and high-counted-permission > (as many perm as many posts in system multiple 3) solution that Les > proposed, use spatial permissions, and just define a finite PostAuthorSpace, > and allow editing/deleting for all posts that has 0 distance from current > user. > > Les, sorry, I could not resist ;) > > Thanks, > ~t~ > > > > On Wed, Dec 1, 2010 at 10:34 PM, Les Hazlewood <[email protected]> > wrote: >> >> Oops. In the instance-level approach, the 2nd code check would be: >> >> if (SecurityUtils.getSubject().isPermitted("post:read:" + postId) ) { >> //show the post >> } >> >> This is the correct check to execute at runtime - an instance-specific >> check, and _not_ SecurityUtils.getSubject().isPermitted("post:read")). >> This latter check (isPermitted("post:read")) says "if the current >> user has the ability to read all posts, show the current post". This >> is slightly incorrect, because what you _really_ want to check is >> "does the current user have the ability to read the current post". >> The difference is subtle, but it is a crucial point to understand when >> using implication logic to build security policies. >> >> If the user is assigned the "post:read" permission, then that >> _implies_ post:read:postId Runtime permissions checks should be as >> specific as possible, while permission assignments can be (and usually >> are) more general (e.g. "post:read"). >> >> Regards, >> >> Les >> >> On Wed, Dec 1, 2010 at 1:26 PM, Les Hazlewood <[email protected]> >> wrote: >> > There are a number of ways to solve this. >> > >> > One way is that you assign permissions to a user that reflect the >> > instances they can interact with. >> > >> > For example, if you assign the user the "post:read" permission (using >> > Shiro's WildcardPermission syntax), then that user will be able to >> > read all posts, e.g. subject.isPermitted("post:read") === true >> > >> > You can further assign permissions according to individual Post >> > instances. Maybe you assign a permission at the time the user creates >> > the post: >> > >> > Post post = new Post(); >> > ... >> > long postId = postDAO.create(post); >> > String editPostPermString = "post:edit:" + postId; >> > >> > long currentUserId = (long)SecurityUtils.getSubject().getPrincipal(); >> > >> > userService.assignPermission(currentUserId, editPostPermString); >> > >> > Then, when a user visits a post page, you can check: >> > >> > if ( SecurityUtils.getSubject().isPermitted("post:edit:" + >> > requestPostId) ) { >> > //show the edit button >> > } >> > if ( SecurityUtils.getSubject().isPermitted("post:edit") ) { >> > //general read request by anyone - show the post. >> > } >> > >> > Don't forget to 'unassign' the permission from the user when you >> > delete the post to make sure you don't have 'permission assignment >> > orphans'. The downside of this approach is that the number of >> > individual permissions assigned to the user can be very large, so your >> > Realm implementation and the data model supporting the permission >> > checks must be efficient. >> > >> > Another approach is to combine the WildcardPermission check and a data >> > model check: >> > >> > For example: >> > >> > Post post = blogService.getPost(request.getParameter("postId")); >> > >> > boolean read = SecurityUtils.getSubject().isPermitted("post:read"); >> > boolean edit = isPostEditable(post); >> > >> > private boolean isPostEditable(Post post) { >> > User currentUser = >> > userService.findUser(SecurityUtils.getSubject().getPrincipal()); >> > if (currentUser.getId() == post.getAuthor().getId()) { >> > return true; >> > } >> > return false; >> > } >> > >> > You could also find this out via a join query: >> > >> > select p.author_id from posts p where p.id = ? >> > >> > As you can see, the 2nd approach is _very_ dependent upon your data >> > model, so it would be difficult for Shiro to support this 'out of the >> > box'. If anyone has any ideas that can make this even easier, please >> > speak up! >> > >> > This is just a high-level approach of how you might do this in your >> > own app, but hopefully this gives you some ideas. >> > >> > HTH, >> > >> > Les >> > >> > >> > On Wed, Dec 1, 2010 at 12:30 PM, acec acec <[email protected]> wrote: >> >> Hi, all >> >> If I want to support the following function by shiro: >> >> >> >> The user can read all post, but can only edit/delete his own post. >> >> >> >> Is there any example for this kind of function? >> >> >> >> Thanks. >> >> Acec
