Spring Security专栏(基于方法级别的保护02)

352 阅读3分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

写在前面

上文我们讲到通过 @PreAuthorize 注解 就能实现对方法的保护,今天我们继续来讨论针对方法级别的安全访问的另一个策略。

这里多唠叨一句,欢迎大家查看我的专栏,目前正在进行的Security专栏和队列并发专栏,设计模式专题(已完结)

使用注解实现方法级别过滤

上文我们讲解使用注解实现方法级别过滤,今天我们来讲讲如何通过注解实现方法级过滤

针对方法级别过滤,Spring Security 同样提供了一对注解,即分别用于预过滤和后过滤的 @PreFilter 和 @PostFilter

@PreFilter 注解

在介绍使用 @PreFilter 注解实现方法级别过滤之前,我们先要明确它与 @PreAuthorize 注解之间的区别。通过预授权,如果方法调用的参数不符合权限规则,那么这个方法就不会被调用。而使用预过滤,方法调用是一定会执行的,但只有那些符合过滤规则的数据才会正常传递到调用链路的下一层组件。

接下来我们看 @PreFilter 注解的使用方法。我们设计一个新的数据模型,并构建如下所示的 Controller 层方法:

@Autowired
private ProductService productService;
 
@GetMapping("/sell")
public List<Product> sellProduct() {
        List<Product> products = new ArrayList<>();
 
        products.add(new Product("p1", "yn1"));
        products.add(new Product("p2", "yn2"));
        products.add(new Product("p3", "yn3"));
 
        return productService.sellProducts(products);
}

上面代码中的 Product 对象包含了商品的编号和用户名。然后,我们来到 Service 层组件,实现如下所示的方法:

@PreFilter("filterObject.name == authentication.name")
public List<Product> sellProducts(List<Product> products) {
        return products;
}

这里我们使用了 @PreFilter 注解对输入数据进行了过滤。通过使用“filterObject”对象,我们可以获取输入的 Product 数据,然后将“filterObject.name”字段与从安全上下文中获取的“authentication.name”进行比对,就能将那些不属于当前认证用户的数据进行过滤。

@PostFilter 注解

同样,为了更好地理解 @PostFilter 注解的含义,我们也将它与 @PostAuthorize 注解进行对比。类似的,通过后授权,如果方法调用的参数不符合权限规则,那么这个方法就不会被调用。如果使用后过滤,方法调用也是一定会执行的,但只有那些符合过滤规则的数据才会正常返回。

@PostFilter 注解的使用方法也很简单,示例如下:

@PostFilter("filterObject.name == authentication.principal.username")
public List<Product> findProducts() {
        List<Product> products = new ArrayList<>();
 
        products.add(new Product("p1", "yn1"));
        products.add(new Product("p2", "yn2"));
        products.add(new Product("p3", "yn3"));
 
        return products;
}

通过 @PostFilter,我们指定了过滤的规则为"filterObject.name == authentication.principal.username",也就是说该方法只会返回那些属于当前认证用户的数据,其他用户的数据会被自动过滤。

通过上述案例,你可能已经认识到了各个注解之间的微妙关系。比方说,@PreFilter 注解的效果实际上和 @PostAuthorize 注解的效果有点类似,但两者针对数据的处理方向是相反的,即 @PreFilter 注解控制从 Controller 层到 Service 层的数据输入,而 @PostAuthorize 反过来限制了从 Service 层到 Controller 层的数据返回。在日常开发过程中,你需要关注业务场景下数据的流转方向,才能正确选择合适的授权或过滤注解。

小结与预告

这一讲我们关注的重点从 HTTP 端点级别的安全控制转换到了普通方法级别的安全控制。Spring Security 内置了一组非常实用的注解,方便开发人员实现全局方法安全机制,包括用于实现方法级别授权的 @PreAuthorize 和 @PostAuthorize 注解,以及用于实现方法级别过滤的 @PreFilter 注解和 @PostFilter 注解。我们针对这些注解的使用方法也给出了相应的描述和示例代码。

下面给幅图便于大家记忆:

image.png

弦外之音

感谢你的阅读,如果你感觉学到了东西,您可以点赞,关注。也欢迎有问题我们下面评论交流

加油! 我们下期再见!

给大家分享几个我前面写的几篇骚操作

copy对象,这个操作有点骚!

干货!SpringBoot利用监听事件,实现异步操作