Hide / remap field values in Hibernate entity based on user permissions
In a Spring 2.6 / JPA 1 / Hib开发者_Python百科ernate 3.3 application I need to "hide" some entity field data based on the current user's permissions.
E.g. on an entity "Document" there's a field "title" which maps to the title column in the DOC table. Depending on the user's permission the title should either read "CONFIDENTIAL" if he/she is not allowed to read the title or it should just contain the correct value as fetched from the database. The same applies to a lot of other properties.
The problem is that I cannot apply a presentation model or some filtering in the UI. This is because the entity objects will get passed to another layer that takes care of post-processing and finally displaying the data in the UI and the real data (i.e. the real value of "title") should not get passed to that layer in terms of being publicly accessible. So the entity object itself should be "sealed" without the real value being accessible through the API - but the entity may store it's state internally of course.
A naive approach would be to fetch the list of Document objects, then iterate over it and set the title to "CONFIDENTIAL" if the user is not allowed. Of course, this will change the entity so when it gets send back to the persistence layer, on merge the value of the title ("CONFIDENTIAL") will get written to the database - which should not happen at any case of course.
So either, I'll have to write custom insert/update statements for these entities (lots of work) and / or write custom loader logic which exchanges the data in the entity - but then again I don't know how to store and track the original state of the entity when it comes to merging. Also, this will fail when using a JPQL/HQL and not the EM methods for loading.
So, my questions are:
- what options do I have to "remap" the value in the entity based on the current user while not breaking the update / merge mechanism?
- could interceptors (either Hibernate or Spring / AOP style) could help out here? But again: how to handle the merge?
Thanks, Dwight
One option that springs to mind is to write a spring aspect to apply across an appropriate layer of your app (service layer?) that will switch values out as entities cross the layer boundary. On the way out, it will change the value from "my secret value" to "CONFIDENTIAL", and it will remember the old value and which entity it came from. Then, if/when the entity is passed back in, it will set "my secret value" back into its place. Thus on your side of the boundary, the entities will always have the proper values, but the secret values never leave the boundary and so can never be compromised.
精彩评论