3
votes

We are using Spring Security's ACL Annotations to allow access to certain web services. @PreAuthorize and @PostAuthorize seems to be extremely useful and favours most of the use cases we are having. The SPEL based rules on individual methods et al are helping us in fine grain security on the application and its services.

For eg:- We check the owner of a returned object as below

@PreAuthorize("hasRole('ROLE_ADMIN') and returnObject.owner == authentication.name")
public SomeDTO getSomeDTO(){ ... }

This works fine when a single object is returned. What would be the equivalent if a List is returned? How do we loop through a collection and check individual element properties in that collection using SPEL?

3

3 Answers

2
votes

In case of a collection you should use @PreFilter and @PostFilter annotations.

When using the @PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false. The name filterObject refers to the current object in the collection. You can also filter before the method call, using @PreFilter, though this is a less common requirement.

See the example below or find more details here.

@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostFilter("filterObject.owner == authentication.name")
public List<SomeDTO> getAll();
1
votes

It depends on your needs.

If you intent to filter out non-permitted objects from the results, you could use the @PostFilter annotation that would filter out the non-matching elements. example (filterObject is bound to a single list element from the response):

@PostFilter("filterObject.owner == authentication.name")
public List<SomeDTO> getAll(){ ... }

If you intent to return the result only if all the elements are permitted, @PostFilter won't help you and you could try using the SPEL's hasPermission function inside a @PostAuthorize annotation. Has Permission can get any type of object and check it logically using your custom implementation (which you'll need to write). for an example, you could refer to this example (section 4)

0
votes

Try the following expression and see.

@PreAuthorize("hasRole('ROLE_ADMIN') and returnObject.?[owner == authentication.name].size() == returnObject.size()")
public List<SomeDTO> getSomeDTOs(){ ... }

See this post.