简体   繁体   中英

How do @PostFilter and @PreFilter work in Spring Security?

Being new to Spring's security annotations, I need a clarification for the below code.

@PostFilter("hasPermission(filterObject, 'READ') or hasRole('ROLE_ADMIN')")
public List<User> getUsers(String orderByInsertionDate,
            Integer numberDaysToLookBack) throws AppException

So this means that the list of users returned by getUsers will only contain those elements which have full "READ" access to the calling object or the calling object has role as "ROLE_ADMIN" . Thanks.

@PreFilter and @PostFilter are designated to use with Spring security to be able to filter collections or arrays based on the authorization.

To have this working, you need to use expression-based access control in spring security (as you have in your example)

@PreFilter - filters the collection or arrays before executing method.

@PostFilter - filters the returned collection or arrays after executing the method.

So, let's say your getUser() returns List of Users. Spring Security will iterate through the list and remove any elements for which the applied expression is false (eg is not admin, and does not have read permission)

filterObject is built-in object on which filter operation is performed and you can apply various conditions to this object (basically all built-in expressions are available here, eg principal , authentication ), for example you can do

@PostFilter ("filterObject.owner == authentication.name")

Though those filters are useful, it is really inefficient with large data sets, and basically you lose control over your result, instead Spring controls the result.

Since the currently accepted answer didn't go into @PreFilter, here's my two cents:

(Quote from the JavaDocs )

Annotation for specifying a method filtering expression which will be evaluated before a method has been invoked. The name of the argument to be filtered is specified using the filterTarget attribute. This must be a Java Collection implementation which supports the remove method.

@PreFilter operates on the method arguments, not the return value. If the annotated method only has a single Collection argument, then the filterTarget annotation argument can be omitted.

The other answers are pretty clear about the rationale and effects of @PreFilter and @PostFilter .

I just feel obliged to add an information about the method output type - both these annotations work with collections, arrays, streams and maps . Be careful to use them with for example Optional . Although to me it's pretty natural to filter an Optional (you think of it as of the collection with at most one element), this will throw the following exception since spring-security-core 5.4.1:

java.lang.IllegalArgumentException: Filter target must be a collection, array, map or stream type, but was Optional[0]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM