使用 MS SQL 的 JAX-RS 中的行级安全性
Posted
技术标签:
【中文标题】使用 MS SQL 的 JAX-RS 中的行级安全性【英文标题】:Row-level security in JAX-RS using MS SQL 【发布时间】:2017-02-24 01:55:08 【问题描述】:我的团队正在 JAX-RS 中设计一个 RESTful API,我们需要根据经过身份验证的“操作员”(我们对用户的话)的 ID 来限制数据库中某些行的可用性。换句话说,运营商应该只能访问其管辖范围内的实体。在每个请求开始时,我们会对发出请求的 Operator 进行身份验证,从而允许我们根据 Operator 的角色和 ID 提供安全功能。
授权端点、端点方法甚至实体内容(被序列化的内容)已被证明相当简单,但行级授权似乎是一头毛茸茸的大野兽。
请注意,我们不使用 Spring,并且没有计划在我们的项目中使用 Spring Security。
我们已经提出了一些潜在的解决方案,但我们不确定哪个是最好的。也很可能有我们没有考虑过的解决方案;在这一点上,我对任何事情都持开放态度。以下是我们目前的成果:
-
数据库级实现(如this post 中所述)。这可能涉及使用请求的安全上下文在每个请求上将操作员的 ID 传递给数据库。我不清楚实现这种方法的具体细节,所以如果这是实现行级安全的最佳方法,我会很感激一些进一步的建议。例如,这对于实体检索来说是有意义的,但我们如何修改新创建或更新实体的行级权限?
JPA 级别实现(如 2008 年的 this post 中所述)。这可能涉及生成一个参数化的 Hibernate 过滤器,我们将向其中输入发出请求的 Operator 的 ID。我从来没有使用过 Hibernate 过滤器,所以这个想法很可能是错误的。
外观级实施。我们实际上已经对这个想法进行了相当多的思考,因为直到最近我们才知道选项(1)和(2)。这将涉及在我们的表之间执行连接以构造一个 Criteria API 谓词,该谓词将我们的查询限制为仅包括给定 Operator 可访问的那些实体。据我了解,这本质上是“手动”方法,似乎远非理想。
如果熟悉 JAX-RS 和/或数据库安全性的人能够帮助理解这一切,那就太棒了。
这是我们项目的技术堆栈(至少与此问题相关):
数据库:MS SQL JPA 提供者:休眠 JAX-RS 实现:RESTEasy【问题讨论】:
除非您使用 SQL Server 2016,否则您可以将 DB 标记为实现行级别安全性的一种方式:行级别安全性 (RLS) 是一个在数据库层内的行级别提供安全性的概念,而不是在应用层。 RLS 是通过使用 SQL Server 2016 推出的函数和新的安全策略特性来实现的。 为什么需要行级安全性? 是否可以选择使用 SQL Server 2016? @MisterPositive 对于我们的项目来说,每个用户的信息都只能被该用户以及层次树中该用户之上的所有用户访问,这一点至关重要。我可能误解了行级安全性的用途,所以如果我走错了方向,请随时纠正我! 您可能需要考虑组/角色方法。如果您实际上必须查看查询返回的每一行数据,从资源的角度来看,这将是非常昂贵的。 【参考方案1】:我对这个主题的思考超出了我的预期,但经过大量思考,我形成了以下观点:它必须通过连接来完成,在数据库级别。从数据库 POV 中,除了遵循外键链到达某个用户(在您的情况下为操作员)之外,没有办法分辨谁是行的“所有者”。没有直接的声明方式来定义行级安全性(在代码中)是有道理的,因为注释不能放在“行”(实体类的实例)上,只能放在编译时可用的代码元素上(即, 方法)。因此,行级别的安全性必须以编程方式完成,并且将“管辖权”视为一个业务概念,它只能通过将实体加入匹配当前用户(或他们所属的组)的操作员来强制执行。 我认为永远不会有更好的解决方案,除非 JPA 会引入注释以将关系标记为“所有者”概念,并引入注释以将实体标记为“所有者”。那样的话,也许 JPA 可以自动为您执行连接......但在那之前,只需将当前用户 ID 传递给您的 DAO/存储库并在您的 JPQL/标准查询中添加一堆连接。这将过滤掉来自其他司法管辖区的行。
【讨论】:
【参考方案2】:使用 SQL Server 2016:行级安全性 (RLS) 是一个概念,它在数据库层内的行级而不是在应用程序层提供安全性。 RLS 是通过使用 SQL Server 2016 推出的函数和新的安全策略特性来实现的。(如果您确实需要行级安全性)
【讨论】:
与在应用层实现行/实体级别安全相比,这是否是一种更好的方法?以上是关于使用 MS SQL 的 JAX-RS 中的行级安全性的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 2019 中 Polybase 外部表的行级安全性可能吗?
如何实现对亚马逊 Redshift 的原始 sql 访问的行级安全性 (RLS)?