身份与权限
我们经常看到人们滥用身份服务器作为授权/权限管理系统。这很麻烦 - 这就是原因。
IdentityServer(因此得名)非常擅长在系统中的所有应用程序中为您的用户提供稳定的身份。对于身份,我的意思是不可变的身份(至少在会话的生命周期内) - 典型的例子是用户ID(又名主题ID),名称,部门,电子邮件地址,客户ID等...
IdentityServer不太适合让客户端或API知道这个用户被允许做什么 - 例如,创建客户记录,删除表格,读取某个文档等...
这本身并不是身份服务器的弱点 - 但身份服务器是一种令牌服务,而且声明(尤其是令牌)并不是传输此类信息的特别好的媒介,这是一个事实。有几个原因:
- 声明应该对用户的标识进行建模,而不是对权限进行建模
- 声明通常是简单的字符串 - 您通常需要更复杂的内容来对授权信息或权限进行建模
- 用户的权限通常不同,具体取决于它使用的客户端或API - 将它们全部放入单个身份或访问令牌中会令人困惑并导致问题。相同的权限甚至可能具有不同的含义,具体取决于谁在使用它
- 权限可以在会话的生命周期内更改,但获取新令牌的唯一方法是往返令牌服务。这通常需要一些不太可取的UI交互
- 权限和业务逻辑经常重叠 - 您希望在哪里划线?
- 唯一确切知道当前操作的授权要求的一方是发生的实际代码 - 令牌服务只能提供粗粒度的信息
- 您希望保持代币较小。浏览器URL长度限制和带宽通常是限制因素
- 最后但并非最不重要的一点是 - 向令牌添加声明很容易。很难删除一个。你永远不知道是否有人已经对它产生了严重的依赖。添加到令牌中的每个声明都应仔细检查。
换句话说,将权限和授权数据保留在令牌之外。一旦靠近实际需要授权信息的资源,就将授权信息添加到上下文中。即便如此,使用声明对权限进行建模也很诱人(Microsoft 服务和框架会将您推向这个方向) - 请记住,简单的字符串是一种非常有限的数据结构。现代编程语言具有比这更好的构造。
角色呢?
这是一个非常普遍的问题。角色是身份和授权之间的灰色地带。我的经验法则是,如果某个角色是系统每个部分都感兴趣的用户标识的基本部分,并且角色成员身份不会或不经常更改,则该角色是令牌中声明的候选项。例如,客户与员工,或患者与医生与护士。
角色的所有其他用法 - 特别是如果角色成员身份根据所使用的客户端或 API 而不同,则这是纯粹的授权数据,应避免使用。如果您意识到用户的角色数量很高或正在增长,请避免将它们放入令牌中。
结论
设计为标识和权限的完全分离(这只是身份验证与授权的重新迭代)。获取尽可能接近需要它的代码的授权数据 - 只有在那里,您才能做出明智的决定,您真正需要什么。
我也经常遇到这样的问题,如果我们有一个类似于IdityServer身份验证的灵活授权解决方案-答案是-现在-不。但我有一种感觉,2017年将是我们最终解决授权问题的一年。敬请期待!
浙公网安备 33010602011771号