基于声明的授权是否适用于单个资源

时间:2018-08-29 14:08:58

标签: authorization access claims-based-identity claims

我了解通常用于“角色”或“权限”的要求的用法。我知道声明更为笼统,但从我在实践中所看到的,通常可以归结为:如果用户拥有这组声明,则可以访问某些区域或执行某些功能。

想象一个Wiki应用程序。您可能有一个允许用户添加内容的 content_contributor 声明,一个允许用户删除内容的 content_admin 声明以及一个 modify_user >可以允许将贡献者权限授予其他用户的声明。

更进一步,我可能希望限制用户,以便他们只能看到自己或团队创建的内容。

如果用户只能看到他们自己创建的内容,我们是否会对他们创建的每个内容都拥有版权,还是将授权授权给应用程序?

1 个答案:

答案 0 :(得分:6)

当您谈论角色 权限时,您谈论的是授权

对于授权,索赔通常。 (Identity)可以对用户的身份进行建模:?声明本身并没有说明授权。用户可以提出角色声明,但这并不能告诉应用程序允许用户做什么

授权由应用程序根据用户身份完成。将授权视为一组规则,例如:

  • 18 + :允许用户年龄超过18岁( DateOfBirth )。

  • 使用汽车:当用户拥有驾驶执照时允许。

或者类似的东西。

角色有点混乱,因为它们经常被误用于授权。请阅读this article了解一些背景信息。

IMO角色的问题是这些角色不是通用的。我可以在一家医院担任医生,而在另一家医院担任患者。对于一个租户,我可以是 Admin ,对于另一个租户,我可以是 User 。因此,它们仅在特定上下文中具有意义。

将角色包括在内的唯一原因是您无需查找此信息,因为它已经存在。但是,鉴于前面的评论,您实际上不能包含此信息。而且只会在您这样做时让您头痛。因为您无法执行更新或更改权限或配置文件设置之类的简单操作,所以直到用户再次登录。

因此,根据经验:使授权靠近资源(API /网站)。因为那是执行业务规则的地方。这就是您可以存储和更新权限等的地方。

关于身份验证和授权,请分开关注。身份验证告诉您用户是谁,授权告诉您允许用户做什么。不要将两者混在一起。


将其翻译为您的Wiki应用程序:

创建一个单独的上下文,在其中存储角色和权限之类的授权信息。您可以在中央资源中(对于多个应用程序)进行管理,也可以在应用程序中使用上下文。我不会将此上下文与业务上下文混合。

在授权上下文中添加用户,并添加角色 content_contributor 。在应用程序内(根据 sub 声明)读取该用户的权限(从中央API,本地授权上下文,设置文件或最合适的任何文件)。将其缓存以提高性能,并应用规则来确定是否允许用户访问资源。

您可以使用resource-based authorization进行扩展。将 sub 声明的值保存在内容记录中以标识所有者。当前用户与 sub 声明值匹配时,当前用户就是所有者。

您可以对团队使用相同的方法。将团队表添加到业务环境,并将用户链接到一个或多个团队。在业务上下文中,直接将 sub 索赔值直接使用 sub 索赔值,或使用Users表间接使用Users表。如果您想显示此信息(例如在报告中),可以添加名称等。

您可以保存团队ID 和/或用户ID sub 声明值(所有者与当前用户是同一团队的成员)在内容记录中,以确定允许的用户访问权限。


我的设置如下:

身份上下文:用户+用户声明。仅用于身份验证。独立于应用程序。

授权上下文:用户(标识=子声明)+每个应用程序:角色,权限等。在单独的“本地”数据库或中央数据库中。仅用于授权。

业务环境:用户(Id,名称,“外键”从属声明,由于表不在上下文中而没有实际的数据库关系)+团队,配置文件,设置等。链接到省略用户表时的 sub 声明值。

为了使业务上下文中的users表保持最新,请定期刷新值。例如,您可以在x时间后用户登录时更新值。或不时查询身份上下文(使用API​​)以请求用户信息(使用身份用户信息端点)。

在所有情况下都可以有一个 users 表,但是它们都有不同的含义并包含其他信息。因此,没有多余的信息。

授权发生在应用程序内部,基于业务规则(策略)和来自授权上下文的授权信息。

最后,当当前系统需要角色声明时(例如User.IsInRole()[Authorize("role")]),您可以(从缓存中)读取每个调用的角色/权限并将其添加到当前用户的声明集合(声明转换)。