I am not really fond of the super class route. Is there a way to wire this externally without modifying the pages?
e.g. pages don't know if they are secure or not Can you wire in an additional listener/interceptor from hivemind for this purpose? Matt -----Original Message----- From: Robert Zeigler [mailto:[EMAIL PROTECTED] Sent: Monday, July 10, 2006 10:32 AM To: Tapestry users Subject: Re: Securing Tapestry Applications Hi Jim, good comments generally. The only comment I have at the moment is for #1, tapestry provides a specific listener, which is pageValidateListener. It's called earlier than pageRenderListener. If you're going to go the custom superclass route, implement PageValidateListener for the authentication logic. Robert Jim Steinberger wrote: > Hey all, > > > > I'm listing just a few security issues and possible solutions below. > For the benefit of all, by all means challenge my assumptions, and add > your own problems. But please at least consider my Problem 3 listed > below, as I'm very curious as to whether someone's found a better > elegant solution. > > > > > > Problem 1: Protecting pages from being accessed anonymously > > > > In other words, unless the user is logged in, they should not have > access to any page other than, most likely, your login-page. > > > > A common solution is to create an abstract superclass for your pages > that, in its pageBeginRender listener, redirects to the login page if > there isn't, for example, a User ASO present. > > > > > > Problem 2: Protecting different pages from different logged-in users > > > > This is really just a more-specific version of Problem 1, and you could > use a more-specific version of the solution: create an abstract > superclass that subclasses the superclass from Problem 1 that checks to > ensure that the user is a specific user. > > > > This can be hard to maintain, though, especially if your various pages > can be accessed by various combinations of user-types. E.g. you don't > want to have to create superclass protection-page for every combination > of user-types in your system. Better to, instead, assign a set of > accesses/permissions to your users, and protecting your pages based on > the presence/absence of a specific access, which could be assigned to > multiple user-types. > > > > You also might consider working something like Acegi security into your > system, which can protect a method based on whether a given > role/permission exists. Google revealed at least one project with this > approach: http://www.carmanconsulting.com/tapestry-acegi > > > > > > Problem 3: Protecting the application from logged-in users who are > spoofing form parameters > > > > So, you've ensured that the only users accessing your system have valid > accounts, and are only accessing the pages and interfaces you've given > them. > > > > Well, what if they're malicious, after all, and know how a Tapestry URL > works? They see that when selecting an Entity to edit from a list, that > the URLs differ like so: "...sp=1...", "...sp=2...", "...sp=5...", etc. > Correctly guessing that's the ID of the corresponding Entity, the user > spoofs the URL to be "...sp=10...". Obviously, they should have > permission to edit Entities, since they need to be able to edit their > own Entities, so this page renders correctly. i.e. even with Problems 1 > and 2 solved, there is still the issue of the user being able to modify > data for other users. > > > > We could have our listener method first call an appropriate service > method that determines, in the example above, whether the logged-in user > has permission to edit the given entity. > > > > However, we don't want to violate the DRY principle: if there are > multiple places where a given Entity can be selected for editing, we > would have to add this check in each place. > > > > Is AOP a solution? Through AOP/Acegi/Spring, you could wrap advice > around your service methods that has access to the > currently-logged-in-user. This would be perfect if you were only > verifying the type of the user, but in this case we're determining > validity based on the values of the given method-parameters. Most > service methods will require a different query/method for determining if > the user and the given parameters are a "match", so this would probably > end up requiring a different Aspect for each method, which doesn't > really gain us much. > > > > So ... the best I can come up with at the moment is to pass the User > object into the service methods that need to be protected, and doing the > check inside the method. Persistence layers should perform individual > units of work, relatively agnostic to what environment it exists in. > The service layer, however, is for business logic, and it's certainly > business logic to declare that a user can only edit the Entities that it > owns. And since the User object should be a POJO that is not Tapestry > specific, this doesn't tie the service layer to a particular > UI-implementation. Further, you're defining this logic in only one > place, and your compiler will remind you in each corresponding Tapestry > listener that a given service method must be made aware of what user is > calling it. > > > > A way to improve on this is probably to inject the user-object into your > service object at the object-level instead of the method-level. If > you're using HiveMind for your services, this is simple enough. It's > well-documented how to make Spring services available to > Tapestry/HiveMind - has anyone done the reverse? i.e. made it possible > to inject Tapestry ASOs into a Spring service? > > > > Has anyone tackled this more elegantly than I've described? Perhaps > with a totally different design approach to security and > user-separation? > > > > This problem has other forms ... such as the user tampering with > serialized objects. This would be an even rarer case than above, > however, and partially mitigated if we've ensured the user can only > screw with his/her own information. However, one potential problem that > comes to mind with this has to do with transitive persistence (i.e. if > you're using an ORM like Hibernate, entities attached to the entity > you're persisting might also be persisted). If for some reason you've > mapped your entities so that AddressType is persisted when the Address > it's attached to is persisted, and this is further being serialized in > the HTML, it could be possible for the user to change that AddressType > (which could, of course, be associated with thousands of other > Addresses). Obviously, that example is an anti-pattern that shouldn't > happen in the first place, but it nonetheless illustrates a couple areas > that deserve some critical thinking. > > > > > > Thanks, > > Jim > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] This message, including any attachments, is intended only for the recipient(s) named above. It may contain confidential and privileged information. If you have received this communication in error, please notify the sender immediately and destroy or delete the original message. Also, please be aware that if you are not the intended recipient, any review, disclosure, copying, distribution or any action or reliance based on this message is prohibited by law. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]