Filtering Authorization Method Level#
Filtering Authorization Method Level In Spring Security#
- If we have a scenario where we don't want to control the invocation of the method but we want to make sure the parameters send and received to/from the method need to follow authorization rules, then we can consider filtering.
- The
@PreFilterand@PostFilterannotations are used to filter lists of objects based on custom security rules we define. @PreFilterdefines a rule for filtering a list that is being passed as an input parameter to the annotated method. If the evaluated value is true, the item will be kept in the list. Otherwise, the item will be removed.- For filtering the parameters before calling the method we can use
@PreFilteras below.
| ContactController.java | |
|---|---|
1 2 3 4 5 | |
-
As you can see in the example above, we will use
@PreFilter()to check the subject field ofContactobject is equal with theHellovalue or not. If the value of subject field is not equal withHello, theContactobject will be removed out of the list. -
@PostFilterdefines a rule for filtering the return list of a method, by applying that rule to every element in the list. If the evaluated value is true, the item will be kept in the list. Otherwise, the item will be removed. - For filtering the parameters after executing the method we can use
@PostFilteras the example below.
| ContactController.java | |
|---|---|
1 2 3 4 5 | |
- We can use the
@PostFilteron the Spring Data repository methods as well to filter any unwanted data coming from the database. It means, after queryingContactsfrom the database. OnlyContacthas contactName isHanwill be kept in the return list. Otherwise, the item will be removed.
PreFiltering And PostFiltering Examples#
Database Tables#
- We will create
contactstable which will contain some columns such ascontactName,contactEmail,subjectandmessage. So, let's run the SQL script below to create the table.
1 2 3 4 5 6 7 8 | |
Entity#
- Then in we create the
ContactEntityclass as below:
| ContactEntity.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Repository#
- Let's create
ContactRepositorybelow.
| ContactRepository.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 | |
Service#
- Next, we need to create a service class which call to
ContactRepositoryfor gettingContactEntitiesand map them intoContactDTOs.
| ContactService.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
- The
ContactDTO will look like below.
| Contact.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
Controller#
- Finally, we will create a new api in the
ContactControllerfor gettingContactsby customerId.
| ContactController.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
Configuration#
- Now, to use Method Level Security we will enable it by add the annotation
@EnableGlobalMethodSecurityinto the main class as below.
| CustomDefaultSpringSecurityApplication.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
- The param
prePostEnabled = truemeans we enables Spring Security@PreFilter&@PostFilterannotations. - Now, let's try to add
@PreFilterinto theContactControlleras below.
| ContactController.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
-
As you can see the
@PreFilterwill require all input object have to contain subject equalHellovalue. If not it will be removed out of the list automatically. -
Then in the
ContactService. We will add@PostFilteras below.
| ContactService.java | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
- As you can see the
@PostFilterwill require all object have to contain contactName equalHanvalue. If not it will be removed out of the list automatically.
Testing#
- Now, let's start our Spring Security application and call api
/v1/userwith user emailhan.do@example.comfor login and get the jwt token.
- Then we will use this jwt token to call POST
/v1/contactfor creating Contacts with request's body as below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
- So, with this request body and the
@PreFilterthat we set up, there are only two first contacts that will passed the@PreFilterand saved into the database because they have subjectHello. Let's execute the request and you will received the result as below.
-
As you can see, only two first contacts are saved in the database.
-
Then we will use the jwt token to continue to call GET
/v1/contactsfor getting Contacts. With the current set up for@PostFilterwe will only received the first Contact record in the database because on it has contactName equalHan. Let's execute the request and you will received the result as below.
Conclusion#
@PreFilterand@PostFilterare useful in some special case and easy to use. It helps developers saving for time for writing codes to checking data. However, If we use it for a very large list so it can be a performance issue and inefficient.- For example if we have thousands of
Contactsin our database and we want to retrieve the fiveContactsthat are currently have contactName withHanvalue. If we use@PreFilterthe database operation will fetch all theContactsfirst, and iterate through all of them to filter out the ones that have not contactName withHanvalue.



