@PostFilter 和@PreFilter 如何在 Spring 安全中工作?

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

作为 Spring 安全注释的新手,我需要对以下代码进行说明。

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

因此,这意味着 getUsers 返回的用户列表将仅包含那些对调用对象具有完全 "READ" 访问权限或调用对象具有 "ROLE_ADMIN" 角色的元素。谢谢

@PreFilter@PostFilter 指定与 Spring 安全性一起使用,以便能够根据授权过滤集合或数组。

要使其正常工作,您需要在 spring 安全性中使用基于表达式的访问控制(正如您在示例中所做的那样)

@PreFilter - 在执行方法之前过滤集合或数组。

@PostFilter - 在执行方法后过滤返回的集合或数组。

那么,假设您的 getUser() returns 用户列表。 Spring 安全将遍历列表并删除应用表达式为假的任何元素(例如,不是管理员,并且没有读取权限)

filterObject 是内置的对象,进行过滤操作,你可以在这个对象上应用各种条件(基本上所有的内置表达式都在这里可用,例如principalauthentication) ,例如你可以做

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

虽然这些过滤器很有用,但对于大型数据集来说效率真的很低,基本上你失去了对结果的控制,而是 Spring 控制了结果。

由于当前接受的答案没有进入@PreFilter,这是我的两分钱:

(引自 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 对方法参数进行操作,而不是 return 值。如果被注解的方法只有一个Collection参数,那么filterTarget注解参数可以省略。

其他答案对 @PreFilter@PostFilter 的基本原理和效果非常清楚。

我觉得有必要添加有关方法输出类型的信息 - 这两个注释都适用于集合、数组、流和映射。请小心使用它们,例如 Optional。尽管对我来说过滤 Optional 是很自然的事情(您认为它是最多包含一个元素的集合),但自 spring-security-core 5.4.1 以来,这将引发以下异常:

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