授权服务--返回已授权资源列表

8
什么是检索用户可以访问的所有资源的推荐方法?
在许多示例中,授权被放置在单独的服务中 - 通常是暴露类似于isAuthorized()的方法,该方法可用于单个查询(“用户是否有权使用Resource ABC?”)以及批量查询(“用户是否有权使用以下资源列表中的任何一个?”)。
虽然授权逻辑存在于授权服务中,但授权策略的执行保留在应用程序本身内(例如,基于来自授权服务的结果实际实现对资源的访问的业务逻辑层;或者基于来自授权服务的结果显示/隐藏个别选项的表示层等)。
如果我的数据访问层可能返回数十亿个“资源”,那么最佳方法是什么?业务逻辑层是否查询所有这些数据(通过网络传输所有这些数据),然后将该巨大列表转发到授权服务(再次通过网络),只是为了获得一个巨大的“允许/拒绝”列表发送回业务逻辑?显然,这听起来不太正确。
这是一种情况,我们无法拥有“干净”的数据访问,授权逻辑和业务逻辑分离吗?我应该要求我的数据访问层仅向我返回用户可以访问的所有资源列表,这可能会被实现为简单的数据库连接,但这将要求嵌入到数据访问代码中以确定谁有权访问什么资源在什么条件下(即,授权策略),因此这些策略将分散在我的代码库中(例如,一些授权逻辑将在我的数据访问层中,一些将在我的授权层中等)?
也许性能胜过“干净”的架构,但是否有更好的方法来解决这个问题?

我正在处理一个类似的难题,这个问题出现在我正在开发的一个大型遗留应用程序中。"大结果集"场景很棘手,我绝对不认为像sJhonny所暗示的那样这不是一个问题。虽然所有记录的结果集可能不是一个好的设计,但如果您想提供记录计数或页计数(而且一个好的设计这样做),您仍然会面临这个问题。如果您的数据层建立在不同的技术上,比如SQL存储过程,这将变得更加困难。即使您同意复制您的授权逻辑,它也是用不同的语言编写的! - Snixtor
3个回答

1

认证最好是外部化的。授权通常太依赖于应用程序,难以外部化。这对于小系统可能有效。但对于大系统,您将遇到缩放问题,这已经是您预期的。

另一件事是返回巨大数据集。我觉得这更适合放在报告中。因此,将具有不同要求的首个处理模块与报告模块分开,因为在业务流程中,您需要专注于数据,在报告中需要大量数据和抽象。

授权不是一个层。它是一个方面。如果您没有将其替换为适当的模拟,则应用程序可能无法工作。但是,如果您删除了方面,则应该没有运行应用程序的问题。也许您的程序将不会记录任何内容,或者您将能够看到比允许看到更多的数据,但它仍将正常工作。

那么,授权是否应该从应用程序域外部化?不。它应该与业务逻辑分离。适当的机制:方面(AspectJ、代理模式、模板类模式)。这是我的一般建议。

我针对业务流程中的“大数据”的特殊建议是:尝试正确划分您的领域模型,以获得专注的小数据(主题“可用性”或“用户体验”)。然后返回我的一般建议。

如果你在业务流程中需要处理大量数据:使用“让它工作、让它正确、让它快”的最后一点。将其视为针对特定数据请求的优化,这些请求可能是慢速的或者被期望为慢速的。在这种情况下,使用特殊的SQL查询、预加载、缓存等。DAO层可能是适当的位置,一个缓存方面或DAO层的优化方面,可以用快速的替代实现覆盖“工作慢”的实现。
我提出的建议是针对常规业务用例的。我没有谈论大数据或报告。正如我所提到的,这些领域有不同的要求。

0

我有一个初步的想法,没有任何实际经验作为基础,但乍一看似乎是可行的。

为什么我们需要授权服务?我的观点是,我们之所以需要该服务的某些功能,是因为我们的数据源没有做好完整的工作。如果我们只使用关系型数据库作为数据源,那么数据库可以管理主要类别的授权。我们可以针对视图进行操作,并授予访问这些视图的权限,从而保护表和列。然后,这种类型的规则仍然存在:

员工的薪资信息可以显示给a) 员工、b) 他们的经理和第二线经理、c) HR报酬团队成员。

我认为这样的授权规则具有业务语义,并且最好由授权服务实现,该服务的表达式是基于业务对象的:

 can This employee see That employee's salary?

这不是以表、行和列的形式表达,而是以更粗略、业务相关的粒度表达。实现这一点需要构建一个表达授权规则的数据模型,严格来说这是业务逻辑,我们只是选择重构授权服务来封装实现。

与之相对比的是细粒度的实体授权,以视图、表和列的形式表达。我的观点是,这应该归属于数据源,如果我们的数据源不能或不实现它,那么我们需要在数据访问层中实现它。DAO“知道”它们使用哪些视图/表,并且可能也知道代表谁运行请求的ID,因此决定是否允许访问。

口头上说:DAO有SQL,所以知道实体,所以可以决定。(是的,某些后端可能没有SQL,但DAO是理解正在检索什么的对象。)它可以通过一个方法来增强,以列出哪些访问方法对于给定用户是允许的。

 CustomerDAO.whatIsAuthorised("joeCoder") => READ, QUERY

 CustomerDAO.whatIsAuthorised("phb") => READ, QUERY, UPDATE

0

我没有一个明确的答案来回答你的问题,但是我可以提供一些指引:

  • 你问道:

我的业务逻辑层是否查询所有数据,然后将这个巨大的列表转发到授权服务,只为了得到一个巨大的“允许/拒绝”列表返回给业务逻辑?

嗯,这对我来说似乎不太可能发生。你能想到一个情况,在这种情况下你想向用户展示所有可用记录吗?难道你不觉得更合理的做法是进一步过滤这些记录(例如按类型、日期等),并且你可能还想对它们进行分页,以便用户获得一个适当大小的结果集。

  • 考虑到你很可能只需要在服务之间传递记录标识符,因此你可能会发现这种方法对你来说是可行的。

  • 还要注意,将授权逻辑作为“服务”并不一定意味着它必须驻留在不同的机器上;你可以将其实现为单独的逻辑模块,并仍然在同一台机器上运行(如果需要,可能与应用程序在同一进程中),从而避免网络流量问题。

  • 你正确地观察到,在数据访问的过程中实现授权可能会很棘手。但是,有一些基础设施工具可以帮助你实现。例如- Oracle的虚拟专用数据库(n)hibernate过滤器,我相信还有其他工具。

这些并不是完整的答案,但它们可能会引导您找到适合您的解决方案。
我建议您谷歌搜索“授权框架 + [您喜欢的编程语言]”;我相信已经有人做过了:)


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