

Implementing custom authorization function for Spring’s @Pre and @Post annotations
The @Pre and @Post annotations provide a way to enforce access control through Spring EL expressions, which can invoke methods. Spring provides some default methods that can be used to implement authorization – such as the hasRole() method. We can use it in a @Pre and @Post annotation to ensure that only users of a certain role can execute it. Let me give you a quick example::
1 2 3 4 5 6 |
…. @PreAuthorize("hasRole('USER')") public void someAction() { // Do some stuff } …. |
This code snippet demonstrates that the method someAction() is secured and only users with the “USER” role can execute it. There are several other built-in methods that are described in the Expression-Based Access Control section of the Spring Security Reference. Sometimes, however, the built-in functionality isn’t enough to address all of the system’s needs. Luckily, in such cases, it’s quite easy to implement our custom authorization method.
Spring allows us to reference components in the @Pre and @Post annotations. We can create a service and call its methods in the @PreAuthorize annotation. We need them to return true or false. If a method returns false, Spring throws AccessDeniedException. In a recent project, we created a class called SecurityService where we put all methods that we used in the authorization. Let me show you an example:
1 2 3 4 5 6 7 |
@Service public class SecurityService { public boolean hasAccess(int parameter) { return parameter == 1; } } |
As you can see, we have a method that returns true if called with parameter = 1 and false otherwise. Now, while this method doesn’t provide authorization logic, it’ll serve as a good example of calling methods with parameters in the @Pre and @Post annotations. Let’s say we want to secure the hasAccess method. We can call it like this:
1 2 3 4 |
@PreAuthorize("@securityService.hasAccess(2)") public void printStuff() { System.out.println("Printing ..."); } |
Notice how we reference our SecurityService using ‘@’ and the name starting with a lowercase. Then we can call the public methods of our service. We called the method hasAccess with a parameter of 2. This will always return false and Spring will always throw AccessDeniedException before the method executes. This is not very useful – but we can implement other logic that takes into account some user attributes. If we wanted to implement the method hasRole() ourselves we would have a method in our SecurityService that takes a String parameter and checks if the user has a role that equals the passed parameter.
Let me show you another very useful thing that we can do in the @Pre and @Post annotations. I’m going to show you the code first and then explain:
1 2 3 4 |
@PreAuthorize("@securityService.hasAccess(#number)") public void printStuff(int number) { System.out.println("Printing ... " + number); } |
I’ve modified the printStuff method from before to include a parameter called number. Spring allows us to pass the value to our hasAccess() method by referencing the number parameter with a ‘#’ symbol. So for example, if I call the method printStuff with a value of 1, Spring will allow me to execute the method and it’ll return “Printing … 1”. If I call the method printStuff with anything else, however, I won’t be able to execute it. This is very useful because we can implement logic that allows the execution of a method based on the passed parameters.
I hope you found this article useful. Do you know a better way to add custom logic in the @Pre and @Post annotations? Let us know below!