Recently I had to quickly secure the service layer of a web application I was working on. I resorted to using AspectJ in order not to have my security related code scattered across the service layer and to also not to touch the service layer code since it was being used in multiple places. Furthermore, Spring was not being used, cause otherwise probably I would have used Spring Security and their annotations. Another benefit that using AspectJ gave us was that we could weave in the security aspects whenever needed. However, this is not the topic of this blog. Since I was the person who wrote the point cuts and the aspects however was not the only one working on the service layer, I wanted to make sure that nobody would add a new method which did not match any of the point cuts and thus is not advised with the security aspects. To make things slightly more complicated, not every method needed to be secured. This approach also helped me while I was defining the point cuts since it automatically identified entry points that have not yet been secured.
What I did was created an abstract test which given a set of interfaces and the service object, will call all the methods on this service object, and fail if any method does not throw a security exception or throws some other exception. I also added the facility to pass a string array of methods that should be ignored. So all I had to do was to extend this test for every service. I still needed to test each service separately to make sure that the methods could be invoked with the right credentials but the abstract test would ensure that all the methods are secured.
If any new method is added which is not captured by any of the security point cuts, then this test will fail and will also identify the method that is not secured.
You can find the code on github here. What I created to illustrate this here is a simple Spring project with a simple service which I accidentally forgot to secure one method. In this project I am using spring security and annotations for ease. The core of the implementation is the AbtractSecurity test.
Then we have a simple test that was implemented which extends the AbstractSecurity test and implements the two required methods, getService which returns the service to be tested and getInterfaceClasses which returns an array of classes.
This might seem like a simple approach, and well, it is and there are a number of ways we could improve on this. For example try to move away from test extension but somehow do this declaratively.
In short, whenever you are developing, think of ways that tests can help you. One should look at tests as tools which empower the developer and aid the developer and not some pesky thing you have to do in order to increase the code coverage report on Jenkins!