如何将 Spring Security @Pre 和 @Post 注释与集合一起使用

Posted

技术标签:

【中文标题】如何将 Spring Security @Pre 和 @Post 注释与集合一起使用【英文标题】:How to use Spring Security @Pre and @Post annotations with collections 【发布时间】:2016-08-18 15:01:41 【问题描述】:

我们正在使用 Spring Security 的 ACL 注释来允许访问某些 Web 服务。 @PreAuthorize@PostAuthorize 似乎非常有用,并且支持我们拥有的大多数用例。基于 SPEL 的单个方法等规则正在帮助我们确保应用程序及其服务的细粒度安全。

例如:- 我们检查返回对象的所有者,如下所示

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

当返回单个对象时,这可以正常工作。如果返回一个 List 会是什么等价物?我们如何遍历一个集合并使用 SPEL 检查该集合中的各个元素属性?

【问题讨论】:

【参考方案1】:

如果是集合,您应该使用@PreFilter@PostFilter 注释。

当使用@PostFilter 注解时,Spring Security 会迭代 通过返回的集合并删除任何元素 提供的表达式为假。名称 filterObject 指的是 集合中的当前对象。也可以在 方法调用,使用@PreFilter,虽然这不太常见 要求。

请参阅下面的示例或查找更多详细信息here。

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

【讨论】:

【参考方案2】:

这取决于您的需求。

如果您打算从结果中过滤掉不允许的对象,您可以使用 @PostFilter 注释过滤掉不匹配的元素。 示例(filterObject 绑定到响应中的单个列表元素):

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

如果您打算仅在所有元素都被允许的情况下返回结果@PostFilter 对您没有帮助,您可以尝试在 @PostAuthorize 注释中使用 SPEL 的 hasPermission 函数. Has Permission 可以获取任何类型的对象并使用您的自定义实现(您需要编写)逻辑地检查它。 例如,您可以参考this example (section 4)

【讨论】:

【参考方案3】:

试试下面的表达式看看。

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

看到这个post。

【讨论】:

这似乎不起作用,但文档似乎是合法的。让我尝试更多的例子,看看

以上是关于如何将 Spring Security @Pre 和 @Post 注释与集合一起使用的主要内容,如果未能解决你的问题,请参考以下文章

在 Grails 中使用 Pre/Post Spring-Security Annotations

以编程方式启用 Spring Security pre-post-annotations

如何在 Grails/Spring Security 插件中禁用 /login/auth

Spring Security pre-authentication - 给我一个新的会话,即使主体没有改变

Spring Security中的多个预授权过滤器?

将 Spring Security 全局方法安全性与 Keycloak 集成