Sam,

I finally read the full text of your message. :-)

There is huge overlap between your requirements and mine.

My application also had the issue that role-based security was not
sufficient. I used a custom imlementation of the Acegi AclProvider to
control (on a per-entity basis) how much could be seen or if links were
generated to access certain records.  This could be used in addition to, or
in place of, the role-based access.

I didn't need to filter result sets as was your case.

I would be very interested in seeing what you have put together. Apart from
the authorization issues, I have yet to see a nice performant Hibernate
table model.

This thread has prompted me to start cleaning up my code and packaging it
into a library. With the carmenconsulting page-level security option on one
end, role and instance-based acl security with my work, and your work
including hibernate-level collection filters there could be a great set of
options for securing tapestry apps.

Jonathan


On 2/27/07, Sam Gendler <[EMAIL PROTECTED]> wrote:

It is simple enough to build a component based on the @If component
which will conditionally check some authorization requirement.  That's
what we have for handling role based auth in a template, including
some sophisticated else handling which lets the template cascade
through a number of options.  We don't explicitly list roles anywhere
in the templates.  We have a delegate that maps permissions from roles
to objects.  Our @IfAuth component just checks whether the current
user has a particular permission (read, write, and deny basically).

We've actually got permissions assigned on a per-property basis on
many objects, so we also have wrapper components which wrap the normal
form components with the IfAuth conditional so that our templates
aren't full of difficult-to-read conditional blocks.  The entire chain
of possible permissions are represented in a single component, so if
they have write permission, they will see a text box, read permission
will show a label, deny will show a blank space, etc.  We actually
went a step further and built a single component which renders any
number of form components based on the type of the value being
assigned.  Booleans get checkboxes, lists get palettes, strings get
text fields, numbers get text fields + number translator, etc.  Each
also takes care of rendering correctly according to the permission
available to the current user for the field in question.  It is
similar to bean form, but pre-dates it by quite a bit.

We do have an IfRole component for the few places where we have to
check whether a user is a particular role, such as when deciding
whether to render a particular menu item.

All of this could plug into Acegi or any kind of authorization
mechanism you might care to roll into your app.  So long as you can
define some kind of AuthorizationDelegate that you can provide to the
tags for doing the auth and returning a permission, it is pretty easy
to implement and/or modify the auth mechanism.

We also have record based security which is implemented entirely via
hibernate filters and AOP interception which ensures that none of the
service methods can be executed without having the appropriate
hibernate filters enabled.  This was necessary in order to handle
things like tables with paging.  The acegi mechanisms don't appear to
provide a way to ensure that db queries only return the rows for which
the current user is authorized, so offset/limit queries don't work
correctly when acegi removes items after the query has run.  This
breaks the paging in the tables.  So we use hibernate filters to
ensure that any query that runs only ever returns the results
appropriate for the current user.

I'm intending to write a paper about this mechanism that folks can
see, as it turned out to be incredibly flexible and very efficient.
It's got unix filesystem style permissions (owner, group, world -
although it is actually a little more sophisticated than that) and
multiple permissions that can be applied to each (read, write,
reassign).  It also provides hierarchical auth, so you have the same
permissions (or better) as any user below you in the hierarchy -
allowing managers to have the same access as their direct reports,
without explicitly assigning them to each record owned by a direct
report. This is vital if any user might ever be moved within the
organization. It also allows temporary owner reassignment without
removing the original owner assignment.  This allows employees to be
assigned to cover for others during vacations and such without forcing
the system to explicitly remember who used to be assigned where and
then reassigning at the end of the period.

The whole thing is completely transparent outside of the service
layer.  The DAO layer knows absolutely nothing about the authorization
filters and neither does the ui layer (except, of course, where we've
exposed fields you can edit to modify assignments and such).  Even our
service layer was almost entirely unchanged, since all filters and
other auth checks are applied in an AOP interceptor. Basically, we
modified the hibernate mapping docs to add the filters, added
interceptors on the service methods in our spring config, and modified
the schema to add the necessary new tables (no changes were necessary
to the entity tables themelves, but new relations were added).

It took a fair amount of research to get the design right, but actual
implementation was surprisingly easy, especially considering that we
had never explicltly implemented a hibernate filter or an AOP
interceptor prior to implementing the row level auth mechanism.  Once
we got the db config dialed in, it only adds about 20% to the worst
queries in the system and is usually much better than that.

If there's interest in the details, let me know.  Maybe that will
motivate me to write the thing up properly.  We had code freeze on
Friday, so I'm just catching my breath from the effort of the release
now.

Here's the basic list of requirements we had to meet:

* Role based authorization on each page (this already existed in our app)
* Role based authorization on each property of any domain object
(already in app)
* User based authorization on a per-record basis
* Actual auth is intersection of role and record auth.  If user has
write access to an entity, they still can only write the fields that
roles they are assigned to have write permission on.
* Must have hierarchical record-level auth (but not hierarchical role
assignment)
* Must be able to assign a user to cover another and then restore back
to original state without having to externally track what original
state was.  Also, if original owner signs on from vacation, they
should still have access (usually)
* Must be able to assign record level auth to groups of users as well
as individuals (also have world assignment, but that is really just a
special group in our implementation)
* Must have multiple 'owners' on any entity (sales maneger, account
manager, external user, etc), each of whom shares the 'owner'
permission
* Must have ability to assign read, write, and reassign permission
independantly to each of owners, group, and world.

Engineering requirements included:

* hierarchy to be dynamically computed rather than manually adding
users to entities based on hierarchy.
* minimize changes to existing code
* must not break any existing functionality like table paging or lazy
loading of collections
* Allow for each owner to have different permission instead of sharing
single owner permission. I know they will ask for it, even if they
don't.

Amazingly, despite extreme misgivings about delivering all of this
functionality along with acceptable performance, I was able to concoct
a mechansim that did all this.  I really had my doubts right up until
I finished my last experiment prior to writing up the design.

--sam


On 2/27/07, Jonathan Barker <[EMAIL PROTECTED]> wrote:
> Mark,
>
> Do a Google search using the search string:
>
> site:http://mail-archives.apache.org/mod_mbox "Jonathan Barker"
>
> I posted some information and code in June 2006 about creating
@Authorize
> and @AclAuthorize based on the code for the tapestry @If component, and
the
> Authorize and AclAuthorize JSP taglibs.
>
> I've had this in production since last May and it's been working
> beautifully.
>
> Jonathan
>
>
> > -----Original Message-----
> > From: Borut BolĨina [mailto:[EMAIL PROTECTED]
> > Sent: Tuesday, February 27, 2007 12:31 PM
> > To: Tapestry users
> > Subject: Re: Role based security
> >
> > Hello Mark,
> >
> > Mark Stang wrote:
> > > Ignore the Mediator class it is one of ours.  The real logic is in
the
> > else.  We store user and role in the visit and check when needed.
> > >
> > >
> > > hth,
> > >
> > sorry, but it doesn't. I am looking for a more general solution - if
at
> > all exists. I wish to lay grounds for security in my Tapestry app
beyond
> > those described in Kent's book EWDT, Tapestry 101 or Beginning POJOS
> > (Novice to Professional). Imagine a portal with several portlets. Each
> > of the portlet is visible and/or editable only to some roles. In a
> > portal server such as Liferay or JBoss Portal you can do this by
> > assigning certain rights to portlets. I don't want to make a
portal(!),
> > but I want to have blocks of code on a Tapestry page protected with a
> > pluggable authorization/authentication mechanism (memory based, LDAP,
> > JDBC, maybe even Active Directory).
> >
> > Cheers,
> > Borut
> > > Mark
> > >
> > > Mark J. Stang
> > > Senior Engineer/Architect
> > > office: +1 303.468.2900
> > > mobile: +1 303.507.2833
> > > Ping Identity
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: Borut Bolcina [mailto:[EMAIL PROTECTED]
> > > Sent: Tue 2/27/2007 7:08 AM
> > > To: Tapestry users
> > > Subject: Role based security
> > >
> > > Hello list,
> > >
> > > I was wondering if there is a better way of securing page components
> > > than using @If components (example from VirtualLibrary for Tapestry
> > > v4.0, Border.html)
> > >
> > > <span jwcid="@If" condition="ognl:admin">
> > >       <tr>
> > >         <td rowspan="1" colspan="1" width="178" height="19"><img
> > > src="/vlib/images/nav/nav_6x1.png" width="178" height="19"
border="0"
> > > alt="Admin"/></td>
> > >       </tr>
> > >       ...
> > > </span>
> > >
> > > <span jwcid="@If" condition="ognl:loggedIn">
> > >       <tr>
> > >         <td rowspan="1" colspan="1" width="178" height="29"><a
href="#"
> > > jwcid="logout"><img jwcid="logoutRollover"
> > > src="/vlib/images/nav/nav_10x1.png" width="178" height="29"
border="0"
> > > alt="Logout"/></a></td>
> > >       </tr>
> > > </span>
> > >
> > > <span jwcid="@If" condition="ognl:!loggedIn">
> > >       <tr>
> > >         <td rowspan="1" colspan="1" width="178" height="29"><a
href="#"
> > > jwcid="login"><img jwcid="loginRollover"
> > > src="/vlib/images/nav/nav_10x1.png" width="178" height="29"
border="0"
> > > alt="Login"/></a></td>
> > >       </tr>
> > > </span>
> > >
> > >
> > > I read all I could find on the list about acegi and a wiki entries
> > > starting at http://wiki.apache.org/tapestry/AcegiSpringJava5, but
none
> > > of the texts mention or suggests something like
> > >
> > > <span jwcid="@Secured" role="acegi:{ROLE_USER, ROLE_ADMIN}">
> > >       <tr>
> > >         <td rowspan="1" colspan="1" width="178" height="19"><img
> > > src="/vlib/images/nav/nav_6x1.png" width="178" height="19"
border="0"
> > > alt="Admin"/></td>
> > >       </tr>
> > >       ...
> > > </span>
> > >
> > > How about creating such component? How do you guys do it?
> > >
> > > Cheers,
> > > Borut
> > >
> > >
> > >
---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> > >
> > >
> > >
> > >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>




--
Jonathan Barker
Consultant

Reply via email to