使用MS SQL在JAX-RS中实现行级安全性

4
我的团队在JAX-RS中设计RESTful API,我们需要根据已认证的“Operator”(我们称之为用户)的ID来限制数据库中某些行的可用性。换句话说,操作员只能访问其管辖范围内的实体。在每个请求开始时,我们对发出请求的操作员进行身份验证,这允许我们基于操作员的角色和ID提供安全功能。
授权端点、端点方法,甚至实体内容(序列化的内容)都相对容易,但是行级授权似乎非常复杂。
请注意,我们不使用Spring,也没有在项目中使用Spring Security的计划。
我们想出了一些潜在的解决方案,但我们不确定哪种最好。也很可能有一种我们还没有考虑的解决方案;我现在对任何事情都持开放态度。以下是我们目前的解决方案:
1. 数据库级别实现(如此帖子中所讨论的)。这可能涉及在每个请求上使用请求的安全上下文将操作员的ID传递给数据库。我不清楚实施此方法的具体细节,因此如果这是执行行级安全性的最佳方法,我会感激进一步的建议。例如,对于实体检索,这是有意义的,但是我们如何修改新创建或更新实体的行级权限呢?
2. JPA级别实现(如2008年此帖子中所讨论的)。这可能涉及生成一个参数化的Hibernate过滤器,其中我们将提供发出请求的操作员的ID。我从未使用过Hibernate过滤器,因此这个想法很可能是错误的。
3. 门面层级别实现。我们实际上已经对这个想法进行了相当多的思考,因为我们最近才意识到选项(1)和(2)。这将涉及在我们的表之间执行连接,以构建一个Criteria API谓词,该谓词将限制我们的查询仅包括特定操作员可访问的实体。就我所理解的而言,这基本上是“手动”方法,似乎远非理想。
如果熟悉JAX-RS和/或数据库安全性的人能够帮助理清所有这些内容,那将是很棒的。
以下是我们项目的技术栈(至少与此问题相关的部分):
- 数据库:MS SQL - JPA提供程序:Hibernate - JAX-RS实现:RESTEasy

1
除非您使用SQL Server 2016,否则可以将DB标记为实现行级安全性的一种方式:行级安全性(RLS)是在数据库层面而不是应用程序层面提供行级别安全性的概念。使用函数和新的安全策略功能来实现RLS,该功能正在SQL Server 2016中推出。 - Neo
为什么需要行级安全性? - Neo
使用SQL Server 2016是一个选择吗? - Neo
@MisterPositive 对于我们的项目来说,每个用户的信息仅对该用户及其在分层树中位于其上方的所有用户可访问是至关重要的。如果我对行级安全性的用途有误,请随时纠正我! - Pablo Napolitano
@MisterPositive 我们确实可以控制使用的 SQL Server 版本,所以从技术上讲这是一个选项,但我们目前没有 2016 版本的许可证。 - Pablo Napolitano
显示剩余2条评论
2个回答

1

使用SQL Server 2016:行级安全(RLS)是一种在数据库层面上提供行级安全性的概念,而不是在应用程序层面上。 RLS通过使用函数和新的安全策略功能来实现,这些功能正在随SQL Server 2016一起推出。(如果您确实需要行级安全)


这种方法比在应用程序层实现行/实体级安全性有何优势? - Pablo Napolitano

0
我已经思考了这个主题比我想象中的要多,但是在大量思考之后,我形成了以下观点:必须通过数据库级别的连接来完成。从数据库的角度来看,除了通过跟随外键链到达特定用户(在您的情况下为操作员)以外,没有其他方法可以确定一行的“所有者”。在代码中,没有直接的声明性方式定义行级安全性是有道理的,因为注释不能放置在“行”(实体类的实例)上,只能放置在编译时可用的代码元素上(即方法)。因此,必须通过编程方式实现行级安全性,并且由于“管辖区域”是一个业务概念,因此只能通过将实体与匹配当前用户(或他们所属的组)的操作员连接来执行。 我认为除非JPA引入一个注释来标记关系为“所有者”的概念,以及一个注释来标记实体为“所有者”,否则不会有更好的解决方案。这样,也许JPA可以自动为您执行连接...但在那之前,只需将当前用户ID传递给DAO /存储库,并在JPQL /条件查询中添加一堆连接即可。这将过滤掉其他管辖区域的行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接