Ocelot、Identity、IdentityServer4和API Resource,如何基于角色授予访问权限



我正在努力学习使用net core的微服务方法

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

  2. 我需要一个入口,奥切洛就是那个。我有这样的配置:

{
"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可以访问公司或读取和公司/写入?

如何真正做到这一点?

非常感谢。

如何在API/角色的基础上授予用户访问权限?

有两种方法:

在客户端

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

如果你只想在用户体验中基于角色的行为——允许/禁止某些调用或隐藏/显示某些屏幕/组件,你可以做以下操作:

  1. 将您的角色建模为Identity Server中的用户声明
  2. 让用户体验询问JWT在登录时返回的持有者,并打开索赔集合
  3. 基于发现的角色应用基于角色的用户体验逻辑

在网关/后端

这更为复杂,但如果您希望在后端具有基于角色的行为,则需要在服务中为此进行编码。例如,实现这一点的一种方法是让每个服务接受一组角色作为头参数。然后你可以:

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

然而,这感觉很笨拙。考虑到服务级别的访问控制,角色感觉有点过于粗糙。

也许还有第三种方式

所以,基于角色的行为在前端很有效,但后端呢?

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

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

GET /customers/{customerId}

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

GET /customers

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

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

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

最新更新