Recently I came across a problem of integrating spring-security into a project that already handled authentication using very application specific approach and also authorization that was very unique to organization needs. Most of the authorization work was done on presentation layer so that according to certain rules links, buttons and forms became visible or invisible. Of course this approach is not safe enough.
The task was to integrate spring-security to secure DAO methods using method level security authorization mechanism that spring-security provides. As you probably know, spring-security uses a concept of "roles" so that each user is assigned one or more roles and each resource to be protected contains information about which roles can access the resource. This can be done using XML or directly in a code using @Secured annotation. But what about cases where application requires different authorization logic? What if organization has hierarchical structure of roles? And what if we need to provide "user" specific authorization rules?
Although this scenario is not very common in certain situations is desirable. In such situations I recommend not to use spring-security even if people have feeling that it solves their problems by just including jars and providing few configuration options. In many cases this can be true but in some having to customize and bend spring-security to certain needs is just overhead. Other example is App Engine. I've also seen instructions of how to use spring-security in Google App Engine. As shown there it's possible, but till now I was able to implement authorization mechanism in a simpler way. Google App Engine recognizes authenticated and unauthenticated users, and for authenticated users there are two roles: "admin" and "user".
Let's have an application that uses spring-mvc with @Controller and @RequestMapping annotations. What we want to achieve is that method "showAllUsers(...)" will be protected and enabled to administrator users only. This is what the code would look like:
This looks pretty simple, let's have a look at @Secured annotation (note: this is application specific Secure annotation, has nothing to do with annotation present in spring-security):
Also quite straightforward, nothing extraordinary here. Spring itself uses "proxy" intensively. For example if you use transactions in your spring application a proxy is created that wraps the code and handles transaction management for you. We'll use the same for the authorization. What we need is a proxy to be created for each controller that has @Secured annotated methods so that we can enable/disable method invocation according to authorization policy. Easiest way to do this? Using @AspectJ, let's see the code of such aspect:
Now we need to add our new aspect into spring context, using xml configuration:
This is enough to secure method invocations. Users need to be authenticated prior invoking any method annotated with @Secured and optionally need to be among administrators if required.
Entire demo application is deployed on GAE and publicly accessible. You'll have to login to be able to access "protected" page, unfortunately you won't be able to access "admin protected" page at all (let me know if you do). All the source code with build and run instructions is also available at GitHub.
This post is also published on GTUG.sk