使用Spring检查实体/对象是否属于当前登录的用户

bal*_*teo 3 spring aspectj spring-mvc spring-security spring-data

我正在使用Spring Web应用程序,该应用程序使用:

  • Spring MVC
  • 春天核心
  • 春天的路
  • 春季安全
  • Spring Data JPA
  • Mysql的

我遇到的问题如下:对于从Web层到应用程序的实体/对象的每次访问,我希望能够检查它们是否确实属于当前用户.

让我举例说明:应用程序的用户有广告,课程(称为实体/对象).我经常使用PK/ID对这些对象/实体执行GET或POST,以便检索,更新或删除这些对象.截至目前,我还没有找到一种干净灵活的方法来阻止用户检索,更新或删除其他人的对象.

我使用Spring Security,我随时知道谁是当前用户(当前登录的用户/委托人),但我不确定在哪里(哪一层)以及如何执行检查.

我曾尝试使用AspectJ建议服务和控制器方法,但我实现它的方式远非理想,因为仅仅方法签名的更改会导致建议不被应用.

我可以在Spring Security中使用ACL,但它增加了一个不必要的复杂层:我只需要授予或拒绝访问给定的实体,无论它们是否属于某个帐户/用户.

任何已经遇到此问题的人都可以提供干净,灵活和干燥的解决方案吗?

Rob*_*ake 5

在我看来,这是一个授权问题.实际上,您希望确认当前用户具有对实体/对象执行操作的正确权限.因此,我建议您的解决方案应用于服务层(中间层).

Spring Security架构的一个重要部分是处理授权决策.值得花时间阅读文档的这一部分,以确保您了解一般架构.

从广义上讲,Spring Security将预调用访问决策委托给a AccessDecisionManager.在AccessDecisionManager一般咨询注册名单AccessionDecisionVoter小号谁,正如其名字会建议对是否允许调用继续根据执行如谁登录在当前的状态,"投票",哪些数据是请求用户.

如何AccessDecisionVoter来决定是否授予访问权限完全取决于执行.因此理论上,您可以做任何事情来决定是否授权特定请求.

值得庆幸的是(正如您所料)Spring提供了一些相当明智的默认实现,可以让您实现开箱即用的功能.特别是我相信Method Security Expressions应该让你实现你想要的(它将取决于你的服务如何实现).

根据文档,您可以将Spring Security的@PreAuthorise注释与一些查看当前方法调用或执行上下文的参数的表达式结合使用.例如:

@PreAuthorise("#u == principal.id")
public List<Foo> loadFoos(@P("u")String userId);
Run Code Online (Sandbox Code Playgroud)

在此示例中,仅当userId参数的值与当前已验证用户的id完全匹配时,才允许继续进行方法调用.

您的确切方法/表达将取决于您的服务如何实施,但希望这为您提供了一个良好的起点.