我正在使用以下的Spring Web应用程序:
我遇到的问题如下:每次访问从网络层到应用程序实体/对象我希望能检查他们是否确实属于当前用户。
让我举例说明:应用程序的用户有广告,课程(称为实体/对象)。我经常使用PK / ID对这些对象/实体执行GET或POST,以便检索,更新或删除这些对象。截至目前,我还没有找到一种干净灵活的方法来阻止用户检索,更新或删除其他人的对象。
我使用Spring Security和我随时知道谁是当前用户(当前登录的用户/委托人)但我不确定在哪里(哪一层)以及如何执行检查。
我曾尝试使用AspectJ建议服务和控制器方法,但我实现它的方式远非理想,因为仅仅方法签名的更改会导致建议不被应用。
我可以在Spring Security中使用ACL,但它增加了一个不必要的复杂层:我只需要授予或拒绝访问给定的实体,无论它们是否属于某个帐户/用户。
任何已经遇到此问题的人都可以提供干净,灵活和干燥的解决方案吗?
答案 0 :(得分:5)
在我看来,这是授权问题。实际上,您希望确认当前用户具有对实体/对象执行操作的正确权限。因此,我建议您的解决方案应用于服务层(中间层)。
Spring Security架构的一个重要部分是处理授权决策。值得花时间阅读section of the documentation以确保您了解一般架构。
从广义上讲,Spring Security将预调用访问决策委托给AccessDecisionManager
。 AccessDecisionManager
通常会查询已注册AccessionDecisionVoter
的列表,正如其名称所暗示的那样,根据当前的执行状态,“是否”允许调用继续进行“投票”。谁登录,用户请求的数据。
AccessDecisionVoter
如何决定是否提供访问权限完全取决于实施。因此,从理论上讲,您可以做任何事情来决定是否授权特定请求。
谢天谢地(正如您所料)Spring提供了一些相当明智的默认实现,可以让您实现开箱即用的功能。特别是我相信Method Security Expressions应该让你实现你想要的(它将取决于你的服务如何实现)。
根据文档,您可以使用Spring Security的@PreAuthorise
注释以及一些查看当前方法调用或执行上下文的参数的表达式。例如:
@PreAuthorise("#u == principal.id")
public List<Foo> loadFoos(@P("u")String userId);
在此示例中,只有userId
参数的值与当前经过身份验证的用户的id完全匹配时,才允许继续进行方法调用。
您的确切方法/表达方式取决于您的服务的实施方式,但希望这为您提供了一个良好的起点。