security - 在域对象中强制执行属性级授权

标签 security rest authorization domain-driven-design

我正在实现一个 RESTful 服务,该服务具有需要在三个级别进行授权的安全模型:

  • 资源级授权 - 确定用户是否有
    访问资源(实体)。例如,是否
    当前用户一般有权查看客户。如果不,
    然后一切都停在那里。
  • 实例级授权 - 确定用户是否有
    访问资源(实体)的特定实例。由于
    各种规则和实体的状态,当前用户可能不会
    被授予访问一组中的多个客户之一的权限
    客户。例如,客户可能能够查看自己的信息,但不能查看其他客户的信息。
  • 属性(property)级授权 - 确定用户的哪些属性
    可以访问资源(实体)的实例。我们有很多
    确定用户是否可以看到和/或更改的业务规则
    资源(实体)的各个属性。例如,
    当前用户可能能够看到客户的姓名,但看不到他们的
    地址或电话号码以及能够查看和添加注释。

  • 实现资源级授权很简单;然而,另外两个不是。我相信实例级授权的解决方案将通过解决(更难的,imo)属性(property)级授权问题来揭示自己。由于我需要在响应消息(ala 超媒体)中按属性传达授权决定,后一个问题变得复杂 - 换句话说,这不是我可以简单地在属性 setter 中强制执行的内容。

    对于对服务的每个请求,我必须使用当前用户的信息来执行这些授权检查。在对资源列表或单个资源的 GET 请求的情况下,我需要告诉 API 层当前用户可以看到(可见)哪些属性以及该属性是只读还是可编辑。 API 层随后将使用此信息来创建适当的响应消息。例如,任何不可见的属性都不会包含在消息中。只读属性将被标记,以便客户端应用程序可以为用户以适当的状态呈现属性。

    应用程序服务、方面等解决方案非常适用于资源级授权,甚至可以用于实例级检查,但我无法确定如何最好地为我的域建模,以便包括实现安全约束的业务规则和检查.

    注意:请记住,这超出了基于角色的安全性,因为我使用资源和环境的当前状态根据业务规则获得最终授权结果(以及使用授予当前用户的权限验证访问)他们的角色)。

    我应该如何对域建模,以便强制执行所有三种类型的授权检查 (以可测试的方式,使用 DI 等)?

    最佳答案

    初始假设

    我假设以下架构:

                                         Stateless Scaling                                          Sharding
                                                 .                                                     .
                                                 .                                                     .
                                                 .                                                     .
                             +=========================================+
                             |  Service Layer                          |
    +----------+             |  +-----------+        +---------------+ |                         +------------+
    |          |    HTTP     |  |           |        |               | |   Driver, Wire, etc.    |            |
    |  Client  | <============> |  RESTful  | <====> |  Data Access  | <=======================> |  Database  |
    |          |    JSON     |  |  Service  |  DTO   |     Layer     | |     ORM, Raw, etc.      |            |
    |          |             |  |           |        |               | |                         |            |
    +----------+             |  +-----------+        +---------------+ |                         +------------+
                             +=========================================+
                                                 .                                                     .
                                                 .                                                     .
                                                 .                                                     .
    

    最初,让我们假设您正在验证 ClientService Layer并获得一个特定的 token ,该 token 对其中的身份验证和授权信息进行编码。

    首先,我首先想到的是处理所有请求,然后仅根据授权对其进行过滤。这将使整个事情变得更简单,更容易维护。但是,当然可能有一些请求需要昂贵的处理,在这种情况下,这种方法绝对无效。另一方面,重负载请求很可能涉及资源级别的访问,正如您所说的那样易于组织,并且可以在Service Layer中检测和授权。在 API或至少 Data Access水平。

    进一步思考

    至于例如和属性(property)级别的授权,我什至不会尝试将其放入Data Access Layer并将其完全隔离在 API 级别之外,即从 Data Access Layer 开始没有任何层甚至会意识到它。即使您请求一个包含 1M 个对象的列表并希望从该特定客户端的所有对象中发出一两个属性,也最好获取整个对象,然后仅隐藏这些属性。

    另一个假设是您的模型是清晰的 DTO ,即简单的一个数据容器,所有的业务逻辑都在Service Layer中实现,特别是 API水平。假设您通过编码为 JSON 的 HTTP 传递数据.所以无论如何,在 API 前面的某个地方层,您将有一个小的序列化阶段,将您的模型转换为 JSON .所以这个阶段是我认为放置实例和属性授权的理想场所。

    建议

    如果涉及到属性级别的授权,我认为没有合理的方法可以将模型与安全逻辑隔离。无论是基于规则、基于角色或基于任何方式的授权,该过程都将根据 Client 提供的身份验证/授权 token 中的一个值进行验证。 .因此,在序列化级别,您基本上将获得两个参数, token 和模型,并相应地将适当的属性或实例作为一个整体进行序列化。

    当涉及为模型定义规则、角色和每个属性的任何内容时,可以根据可用范例以各种方式完成,即取决于 Service Layer 的语言。将实现。可以大量使用 Annotations (Java) 来完成定义。或 Decorators (Python) .为了发出特定的属性,Python 将凭借其动态类型和 hacky 功能派上用场,例如Descriptors .在 Java 的情况下,您可能最终将属性封装到模板类中,例如 AuthField<T> .

    摘要

    综上所述,我建议将实例和属性授权放在API Layer前面。在序列化阶段。因此,基本上,角色/规则将在模型中分配,授权将在序列化器中执行,提供模型和 token 。

    关于security - 在域对象中强制执行属性级授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30002351/

    相关文章:

    azure - 使用 Azure Active Directory 访问其他服务

    amazon-dynamodb - 使用 Cognito 的 DynamoDB 细粒度访问

    api - 有限收集的HTTP状态码?

    api - 传递给 yii\web\User::login() 的参数 1 必须实现接口(interface) yii\web\IdentityInterfac,给定为 null

    java - Java 平台的描述和运行代码是否存在一系列老的安全问题?

    java - Spring 安全问题 - Web 应用程序启动时没有错误,但行为不稳定

    java - 如何将 Java 接口(interface)迁移到微服务?

    c# - 想要在不使用 samAccountName 或 DirectoryServices.AccountManagement 的情况下查找 AD 组的 SID

    security - 红队、渗透测试和蓝队之间的区别

    security - 检测已更改的 Web Api