【问题标题】:Authorization in a layered application分层应用程序中的授权
【发布时间】:2018-04-29 13:52:03
【问题描述】:

我正在从事一个非常简单的项目,该项目主要由 getter 和搜索组成,并且对某些数据的访问受到限制,具体取决于用户。在这种情况下,我想利用这个机会在安全性和授权方面做一些最佳实践。

应用程序被激活一次,此时生成令牌并用于将来的请求。

我的应用程序有一个用于端点的 web api,它位于一组服务之上,而这些服务位于一组位于 sql server db 之上的 repo 之上。控制器所做的只是将请求转发到服务层。

这是一个示例控制器:

[ApiAuthorize]
[RoutePrefix("api/Catalogue")]
public class CatalogueController : ApiController
{
    private ICatalogueService _catalogueService;
    public CatalogueController(ICatalogueService catalogueService)
    {
        _catalogueService = catalogueService;
    }

    [HttpGet]
    [Route("GetCatalogues")]
    public IHttpActionResult GetCatalogues(string branchEan)
    {
        var catalogues = _catalogueService.GetCatalogues(new GetCataloguesRequest()
        {
            BranchEan = branchEan
        });

        return Ok(catalogues);
    }
}

我的自定义授权属性检查令牌,如果有效,则从令牌中提取用户详细信息并创建一个通用原则,然后在我的控制器中可用。

对我来说,Web api 只是一种公开我的业务\服务层的方式,授权应该在我的服务层的较低层完成,但我想不出一种干净的方式将这些信息传递到该层。在上面的示例中,服务层需要检查用户(来自令牌)是否有权访问该特定分支,这意味着服务层需要知道谁在发出请求。我能想到的两个解决方案是:

1) 我正在为我的服务层使用请求\响应模式,因此我可以创建一个名为“请求”的抽象基类作为示例,它可以存储所有用户详细信息,并且服务层的每个请求对象都可以继承自因此,这会向我的服务层提供用户详细信息。

public abstract class Request
{
    public Request(string username)
    {
        this.Username = username;
    }

    public string Username { get; private set; }
}

public class GetCataloguesRequest : Request
{
    public GetCataloguesRequest(string username) : base(username)
    {
    }
}

2) 定义一个接口,例如 ISecurity,然后将其注入我的服务层,但这需要我的服务层之上的层来实现该接口。

我在这里阅读 - Placing authorization into the service layer rather than Web API layer - 创建一个授权层,但我不确定它的技术实现。

有什么想法吗?

【问题讨论】:

  • 研究 IPrincipal、IIdentity 和声明。
  • 我知道这些技术,我正在创建一个通用原则,问题是如何将这些信息从表示层传递到业​​务层
  • 您可以通过方法参数或作为向下层传递的参数的属性显式传递它
  • 这个问题主要是基于意见的。
  • 就像我在原始问题中提到的那样,我不想将它作为参数传递。我理解它的意见,但我需要其他有经验的开发人员的意见才能得出合适的解决方案

标签: c# asp.net-web-api authorization layered


【解决方案1】:

您正在寻找的是细粒度的、外部化的授权:

  • 细粒度:您希望创建考虑多个参数或属性以及客户端(请求者)和目标实体之间可能的关系的授权策略,例如您的案例中的列表。
  • externalized:您希望将业务逻辑与授权逻辑解耦。在您的问题中,您抱怨代码和 SQL 语句变得多么复杂。这是没有明确区分业务逻辑和授权逻辑的直接后果。

有一个称为基于属性的访问控制 (ABAC) 的模型,它定义了一种细粒度外部授权的方法。美国国家标准与技术研究院 NIST 制作了一个report on ABAC,您可以在线阅读。

促进结构化信息标准的组织 OASIS 定义了一个名为 XACML(可扩展访问控制标记语言)的标准来实施 ABAC。

XACML 为您带来:

  • 如下图所示的架构
    • 策略执行点 (PEP) 拦截您的 API 调用。它保护您的 API、检查消息并向策略决策点 (PDP) 发送授权请求。
    • 策略决策点 (PDP) 根据一组用 XACML 编写的授权策略评估来自 PEP 的传入授权请求。 PDP 最终会做出允许或拒绝的决定。为了做出决策,它可能需要从数据库、Web 服务、LDAP 或文件中查找其他属性值。这些在架构中被称为策略信息点。
  • 一种策略语言:XACML 策略语言是基于属性的,这意味着它使用属性来定义什么可以被允许,什么不能。例如,您可以定义如下规则:
    • 当且仅当列表位置 == 代理位置时,房地产经纪人才能查看所有列表
    • 当且仅当房地产经纪人拥有房源时,他/她才能编辑房源
    • 当且仅当列表中的项目已售出并且当且仅当代理是出售该项目的人时,房地产经纪人才能关闭列表。
  • 请求/响应方案:XACML 还定义了一种查询 PDP 并获取响应的方法。可以通过单个问题或通过单个请求中的多个问题来查询 PDP,例如:
    • Alice 可以查看清单 123 吗?是的,允许。
    • Alice 可以查看、编辑或删除列表 123 吗?允许;否定;拒绝。

使用基于 XACML 的方法,您可以将业务逻辑和 API 与授权逻辑分开。这有几个好处:

  1. 您始终可以重新实现 API 并保持相同的授权模型
  2. 无需重写授权即可轻松扩展 API
  3. 您可以独立于代码更改授权逻辑
  4. 您可以更轻松地审核您的授权逻辑
  5. 您的授权逻辑是技术中立的。它适用于 REST API、网络服务、数据库等

我建议您查看以下资源:

  1. OASIS XACML website
  2. ALFA plugin for Eclipse - 用于编写 XACML 策略的免费工具。
  3. XACML developer community

XACML 既有供应商实现,也有开源实现:

  • Axiomatics 是一种供应商解决方案,提供 .NET 和 Java XACML 实现
  • SunXACML 是一个长期存在的开源 Java XACML 实现

HTH, 大卫。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-06
    • 2015-08-16
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2021-11-07
    • 2013-09-15
    • 2022-09-08
    相关资源
    最近更新 更多