I also struggled with something similar and came up with a somewhat
different solution from instance level access control, specifically for
pages (which doesn't seem to fit your need, but I'll mention it anyway). On
a previous project in Grails, we used the Grails Shiro plugin (
http://grails.org/plugin/shiro) , which sets up "by convention"
permissions, where each action that runs requires a permission of the type
"domain:action:id" - e.g. if I want to access book:show:1 , I need to have
the relevant permission (e.g. book:show:1, or book:show:*, or book:*, etc).
In order to implement a similar approach in Tapestry, I added a new
annotation
@DynRequiresPermissions(value = "book:@bookId", tokens = "@bookId=%1s")
// this basically means that shiro will look for a permission
book:@bookIdwhere @bookId is substituted with the first activation
context parameter
class Show {
}
At login time, the user receives the static permissions that they actually
have (e.g. book:1) based on their roles and company membership, and I have
a component request filter that transforms the @DynRequiresPermissions
annotation values into the actual permission that is needed (e.g. from
book:@bookId => book:1), and then passes the permission check to Shiro.
This works reasonably well, as the set of permissions that a user has is
fairly static - once a user is created for the given company and are given
access to a certain set of resources, that doesn't change very often. I
currently don't use the isPermitted, but now that you mentioned it, I
should probably consider doing it (instead of refreshing the static/cached
permissions whenever the user state/access changes).
I'm not sure if this helps but might give you some ideas.
Cheers,
Alex K
On Thu, Oct 11, 2012 at 9:38 AM, Dmitry Gusev <[email protected]>wrote:
> Hi,
>
> I need to implement instance-level access control in my application using
> tapestry-security.
>
> I already asked similar question here [1].
>
> There Taha suggested to use AuthorityVoter, but that wasn't Tynamo's
> tapestry-security.
>
> I looked at Entity-Relationship Based Access Control [2].
>
> This is not exactly what I need, because I don't even have DAO layer
> involved here.
>
> Here's what I have. I have business method in one of my services:
>
> @RequiresPermissions("task:submit")
>
> void submitTask(Task newTask);
>
> I read about ILAC on Shiro's web site [2].
>
> This looks similar, but in my domain not every user may submit every task
> for execution.
> I have custom logic that should inspect instance of the newTask and decide
> whether current user has permissions to submit the task for execution or
> not.
>
> In Shiro's documentation [3] there's a note that tells that a developer may
> write its own implementation of AuthorizingRealm.isPermitted(*) to check
> permissions against custom domain model. I'm not sure about this in my
> case, though, because this note is given in 'Performance Considerations'
> section.
>
> One more thing that stops me from overriding
> AuthorizingRealm.isPermitted(*) is
> I don't have access to invocation context, i.e. I can't get instance of the
> newTask from example above:
>
> AuthorizingRealm realm = new AuthorizingRealm()
>
> {
>
> @Override
>
> public boolean isPermitted(PrincipalCollection principals,
> Permission permission) {
>
> // XXX ... can't access to newTask instance
>
> }
>
>
> I was thinking about fixing Tynamo's SecurityInterceptor advise, by putting
> MethodInvocation into Tapestry Environment service instance and getting
> this MethodInvocation from there in realm.
>
> Am I in the right direction? Any suggestions?
>
>
>
> [1]
>
> http://tapestry.1045711.n5.nabble.com/ANN-A-Tapestry5-Based-Security-Module-tp3322452p3338137.html
> [2] http://tynamo.org/tapestry-security-jpa+guide
> [3]
>
> http://shiro.apache.org/permissions.html#Permissions-InstanceLevelAccessControl
> [4]
>
> http://shiro.apache.org/permissions.html#Permissions-PerformanceConsiderations
>
> --
> Dmitry Gusev
>
> AnjLab Team
> http://anjlab.com
>