【问题标题】:Ocelot, Identity, IdentityServer4 and API Resource, how to grant access on a role basisOcelot、Identity、IdentityServer4 和 API Resource,如何根据角色授予访问权限
【发布时间】:2020-12-26 06:11:08
【问题描述】:

我正在尝试学习使用 net core 的微服务方法应该是怎样的。因此,经过大量教程,这就是我到目前为止所得到的:

  1. 我创建了两个 apis 项目:Company 和 Package。端口 5002 和 5010

  2. 我需要一个网关,Ocelot 就是一个。我有这个配置:

{

  "Routes": [
    // Company Api
    {
      "DownstreamPathTemplate": "/api/company/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5002
        }
      ],
      "UpstreamPathTemplate": "/api/company/{everything}",
      "UpstreamHttpMethod": [
        "GET"
      ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "TestKey",
        "AllowedScopes": []
      },
      "AddHeadersToRequest": {
        "CustomerId": "Claims[sub] > value"
      }
    },
    // Anonymous Company Api
    {
      "DownstreamPathTemplate": "/api/company/getHomeSections",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5002
        }
      ],
      "UpstreamPathTemplate": "/api/anonymous/company/getHomeSections",
      "UpstreamHttpMethod": [
        "GET"
      ]
    },
    // Package Api
    {
      "DownstreamPathTemplate": "/api/package/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5010
        }
      ],
      "UpstreamPathTemplate": "/api/package/{everything}",
      "UpstreamHttpMethod": [
        "GET"
      ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "TestKey",
        "AllowedScopes": []
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5000"
  },
  "AllowedHosts": "*"
}
  1. 我有一个配置了身份和 mongoDB 的 identityServer4。像魅力一样工作。

我已经在 Angular 10 中配置了一个客户端。我可以登录,我得到了令牌,一切都按预期工作。

现在我最大的问题是,如何根据 API/角色授予用户访问权限?那么假设角色 A 可以访问公司/读取,而角色 B 可以访问公司/读取和公司/写入?

实际上是如何实现的?

非常感谢。

【问题讨论】:

    标签: .net-core microservices identityserver4 ocelot


    【解决方案1】:

    如何根据 API/角色授予用户访问权限?

    有两种方式:

    在客户端

    此方法根本不涉及网关,只涉及 IdentityServer。

    如果您只想在 UX 中实现基于角色的行为 - 允许/禁止某些调用或隐藏/显示某些屏幕/组件,您可以执行以下操作:

    1. 将您的角色建模为 Identity Server 中的用户声明
    2. 让 UX 询问登录时返回的不记名 JWT 并解压缩声明集合
    3. 根据发现的角色应用基于角色的用户体验逻辑。

    在网关/后端

    这比较复杂,但是如果您想在后端拥有基于角色的行为,那么您需要在服务中为其编写代码。例如,执行此操作的一种方法是让每个服务接受角色集合作为标头参数。然后你可以:

    1. 将您的角色建模为 Identity Server 中的用户声明
    2. 在 Ocelot 中公开上游服务路径,不带任何角色头参数
    3. 当 UX 发出请求时,让 Ocelot 将“角色”声明作为下游 http 标头注入(与您当前对 customerId 执行的方式相同)
    4. 然后您可以让每个服务根据角色决定是否允许请求

    但是,这感觉很笨拙。考虑到服务级别的访问控制,角色感觉有点太粗粒度了。

    也许是第三种方式...

    那么,基于角色的行为在您的前端很有效,但是您的后端呢?

    由于您已经利用将 CustomerId 用户声明注入下游服务的能力,我们应该考虑另一种解决方案。

    为什么不使用资源标识符来控制后端的访问而不是基于角色的行为?例如,可以使用 customerId 作为路径的一部分来定义与客户相关的私有 http 操作:

    GET /customers/{customerId}
    

    在Ocelot中,上游路径可以暴露为

    GET /customers
    

    customerId声明在网关收到请求时注入下游路径(注意:Ocelot不支持开箱即用的路径参数注入。需要创建一个派生自DelegatingHandler的类,并将其与 ocelot.json 中的 DelegatingHandlers[] 集合一起使用以执行 this)。

    类似地,您可以通过创建从 GET /companyGET /company/{companyId} 的 Ocelot 路由来保护您的公司 API,其中 companyId 是用户声明。

    结合前端基于角色的行为,与基于角色的行为相比,此方法可为您提供对网关/后端的更细粒度的访问控制。两全其美。

    【讨论】:

    • 这是一个非常完整和好的回复!我仍然是老式的,我一直生活在以角色为基础的时代。我会看看你的第三个选项,我觉得它更合适!谢谢!
    • 不用担心。我认为如果服务更像 RPC 样式,则基于角色的访问效果很好。对于资源式服务,最好从公共/私人运营的角度来考虑。这就是为什么我通常不使用 Ocelot 中的 /{everything} 路径进行私有操作的原因。
    猜你喜欢
    • 2020-03-01
    • 2016-06-13
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2020-02-17
    • 2012-02-03
    • 2013-10-15
    相关资源
    最近更新 更多