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

Reply via email to