From: Alef A. \(JTeam\) <al...@jt...> - 2003-07-31 21:36:44
|
> interceptor framework supports postHandle=20 > now in addition to preHandle, allowing e.g.=20 > for binding user contexts from a session=20 > attribute to a ThreadLocal in preHandle=20 > and removing it again in postHandle. Argggh.... I just spent my time breaking my mind over the issue how to do this (and shouting at the framework for not having postHandlerInterceptors ;-). Then I get this email ;-). So to implement the latest and greatest of my features, I will probably have a chance to test this quite thoroughly tomorrow. Some of those features might - btw - be very interesting for addition to Spring, but definitely not for 0.9.1 release!!! Ahh, what the heck, why don't I just already put up the ideas, maybe people have some interesting thoughts... What I'll describe below is already implemented in a working prototype. --- WARNING - NOT FOR THE 0.9.1 RELEASE, JUST A TWIST OF THE MIND --- I've been struggling for ever with the question how to prevent certain users from seeing or being able to edit certain data. And then I don't mean complete objects, just bits of objects. For instance: administrators can create and edit Account-objects, users in their turn can only update their firstName-property and lastName-property (contained by those accounts). I really don't want to - every time I save the Account object - check if the user isInRole(user/administrator) and check if the firstName-property and lastName-property has been set, etcetera. I also don't want to have those checks in my datamodel/objects. It would be perfect if this could done outside the datamodel and also outside the businesslogic. Just like validation. Oh yeah, I don't want to do it with database-views... So today I had a huge fight (design sessions are always fights here, but it's very constructive) with my colleague about this issue. We finally came up with the idea to think up a generic Object/PropertyPermissions framework, of which he would make the implementation that would set permissions based on the combination of Object type and Role (contained by the Principal). To be able to use this in MVC (and more specifically: Spring), I have devised something like the Validator (contained in a new package com.interface21.security), called PropertyPermissionsResolver. This works together with the PropertyPermissions interface and the PropertyPermissions interface. All very abstract and to be implemented just as the validator. PropertyPermissions would apply to the complete Model (in the ModelAndView) and objects in the model will dynamically be passed to the PropertyPermissionInspector (having the same boolean supports()-method as the Validator). So if no Inspector is defined for a certain Object, no permission will be added (or nothing is accessible at all, this would be configurable). Views can use the information of the PropertyPermissions and stuff in their logic to render things accordingly. To facilitate JSP Views I want to a couple of method to the BindStatus object - or extending it for this purpose - (specifically isVisible() and isEditable()) to be able to use the BindStatus for this purpose as well=85 JSP code utilizing this would somewhat look like this: <spring:bind path=3D"Account.active"> <c:if test=3D"${status.editable}"> <intput type=3D"text" name=3D"<c:out value=3D"${status.epxression}"/>" value=3D"<c:out value=3D"${status.value}"/>"> </c:if> </spring:bind> <spring:bind path=3D"Account.fistName"> <c:if test=3D"${status.editable}"> <input type=3D"text" name=3D"<c:out value=3D"${status.epxression}"/> value=3D"<c:out = value=3D"${status.value}"/>"> </c:if> </spring:bind> The above code would result in two textfields for the administrator (both active and firstName) and one textfield for anybody with role 'user' when applying the usecase mentioned above (if of course you would be using the Role/ObjectType based security model!). So only one view, one controller, one model but still hiding certain property from certain users that are not allowed to see them (and a lot more possible functionalities ;-). Right now I've got things implemented for Roles/ObjectTypes and this looks like the following. As you might see, nested property permission are possible using this thing as well=85 This is all pretty specific for our application and way of working, but the interfaces (PropertyPermissions, Inspector, Resolver and stuff) and the complete idea is especially suitable for addition in my opinion, even more since Juergen just added the postHandle things, where this can take place... <object-permission name=3D"jteam.site.data.Account"> <!-- everybody is allowed to see everything --> <property-permission> <role-name>administrator</role-name> <role-name>employee</role-name> <property-name>*</property-name> <editable>true</editable> <visible>true</visible> </property-permission> <!-- the customer cannot edit an account --> <property-permission> <role-name>customer</role-name> <property-name>*</property-name> <editable>false</editable> </property-permission> <!-- define the properties that are nested --> <object-permission-ref property=3D"account" ref=3D"jteam.site.data.Account"/> </object-permission> However, I've got a couple of issues hanging around=85 * The BindStatus things are pretty JSP-specific of course. How to use PropertyPermissions when one's View technology is Velocity? I don't want to (before the view gets rendered) generate all PermissionsObjects up front, because this is all nested and it could well be 100's of objects each request (of which probably only 10% is actually used, considering a form of 10 fields) * What to do with the PropertyPermissionsInspector. There's no place - so far I can see - to put the PropertyPermissions in. I kind of sense they should be part of the model (in the ModelAndView object), but this of course is a major api-change. PropertyPermissions should be usable in any view, not just for instance the JSP view. So somehow the Inspector needs to be available at all times... * How to actually get in the functionality that it=92s not only possible to see if a property is editable, but also to prevent the setter from being called. I smell a bit of AOP here (and I'm not too familiar with it yet), but is it possible to create advises and interceptor dynamically using a security configuration file or something? * How to get extra information in for use when developing custom propertypermissioninspectors. Right now I need to have the principal to determine the role of the user and I'm passing on the HttpServletRequest to achieve this=85 But this does not feel right (see the methods below) Phew=85 that's all basically. Below I'll insert the public API for the object I've mentioned, just so you can take a look=85 /* this one is resembling Errors a lot */ Interface PropertyPermissions ---- // final static permission integer ---- boolean isVisible(String path) ---- boolean isEditable(String path) ---- boolean setNestedPath(Sring nested) ---- void permit(String field, int permissions) /* this is the interface actually determining the permissions */ Interface PropertyPermissionInspector ---- boolean support(Class clzz) ---- /* passing on the servletrequest does not feel right, but see the remark above */ ---- PropertyPermissions determinePropertyPermissions(Object o, HttpServletRequest req) /* this is the to-be-configured collection of Inspector that will be used to apply a security model to the complete Model(AndView), names are crap by the way */ Class PropertyPermissionsResolver ---- /* setter for the propertypermission objects in the xxx-servlet.xml */ ---- void setPropertyPermissionsInspector(List l) ---- /* finds inspector supporting given class and returns PropertyPermissions */ ---- PropertyPermissions getPropertyPermissions(request, response, object) This all would be used from a PostSecurityHandlerInterceptor which I haven't created yet=85. Opinions??? Alef |