Dec 28th, 2004, 01:12 PM
Security and the UI
I'm attempting to develop as clean a solution as possible for securing my UI. In my case this UI is a rich client (spring-richclient/Swing based). I'd like to lay out my initial thoughts for comments or recommendations.
My goal is to declaratively secure the UI. I would like most security information related to the UI to be in a centralized location (maybe in a single Spring config, or even in the DB). The problem I'm having with the declarative approach is that, in my case anyway, the UI reacts dynamically and differently to various security situations. For example, in one case if the user does not have certain roles then it simply removes some columns from a table, in another case the lack of roles may disable a button, in yet another case might cause a button to disappear altogether, in another case it might remove certain fields from a form, etc. In the case of buttons or components disappearing, they need to do so in such a way that the screen layout adjusts in a sensible way (in other words, it doesn't leave a gaping hole where the component should be, making it obvious that something is missing).
My current approach is more practical in nature, meaning that due to time constraints I had to come up with something workable and quickly. I simply assign every securable part of the UI some unique string ID, and then create a single registry (currently a bean that is built via a Spring config) that assigns each ID a set of roles that the user must have in order to access the ID. Then I programatically query this registry in my code. My code is aware of what part of the UI it is working with and the ID associated with that part (which is hardcoded at the moment), and so queries the registry for each UI part ID. If that particular ID is not accessible to the current user, then my code manually reorganizes the UI as needed. In other words, I'm using a declarative/programmatic hybrid approach.
I'd appreciate hearing how other people have approached this situation or any thoughts on my current approach. I'd love to go purely declarative with the UI if possible.
PS I should note that there is redundant security information in the system. The server side has security information on the roles required to invoke service methods and the roles required to access domain objects. It is conceivable that the UI could infer many of its security constraints from the server's security information - but I have not had time to investigate this approach further.
Dec 28th, 2004, 03:37 PM
AFAIK Spring Rich hasn't got a nice Action enable/disable/visible/invisible management approach that integrates with security. Keith and I had hoped to implement one, but haven't had a chance yet...
The approach we intended to use was the ClientSecurityEvent would be received by some sort of Action security manager, which then updated the UI controls based on the Authentication available from the ContextHolder. As you probably know, the classes involved in setting up the ContextHolder with a server-derived Authentication are already in place.
The core of your problem is how to write the Action security manager. I'd suggest reusing several concepts we've found useful in Acegi Security, particularly as there are already documented and unit tested classes that implement them.
First up, you need a mapping between each Action and the ConfigAttributeDefinition that applies. This mapping could be handled in a number of ways, but the most elegant would probably be an ActionObjectDefinitionSource (which extends ObjectDefinitionSource). The ActionObjectDefinitionSource justs maps a String Action key to a ConfigAttributeDefinition, so it would largely be identical to the AbstractFilterInvocationDefinitionSource and optionally its regular expression and Ant-based subclasses.
Your Action security manager would then consume the ClientSecurityEvent, retireve each Action bean's String key, retrieve the relevant ConfigAttributeDefinition from the ActionObjectDefinitionSource, get a void or AccessDeniedException response from an AccessDecisionManager, and change the Action state accordingly.
Once immediate issue is how to differentiate between enabled/disabled and visible/invisible. You could perhaps decide to automatically make an action disabled and invisible if AccessDecisionManager throws AccessDeniedException, and have an actionSecurityManager.setLeaveVisibleConfigAttribu te(ConfigAttribute). If a given action causes an AccessDeniedException and that action definition has a ConfigAttribute that matches the property, it would only be disabled (not made invisible as well).
The above is by no means prescriptive. I've just tried to identify some code areas you might be able to reuse and/or make your approach more pluggable.
I will move this thread to the Spring Rich forum, where it will hopefully get more discussion as it mostly related to how the Action security manager might work, and I think that class is better situated in the Spring Rich codebase.
Dec 28th, 2004, 04:16 PM
This sounds good when it comes to Actions, but not everything that can be secured in a UI is an action. Form fields and table columns come to mind. Since the architecture you describe is based on action ids, I wonder if we could generalize it a little more and simply refer to these string ids as UI ids? I can then "id" any table columns or form fields that need to be secured and assign security attributes to them. There is still the trick of getting the table or form to then hide or disable the column or field. Maybe spring-rich needs a secured form class? It could look up the security attributes for a particular form field the same way it looks up the internationalized label for a form field now - build some sort of id based on the name of the form and the name of the property and then look that up as the UI id in the ObjectDefinitionSource. Thoughts?