当前位置:  开发笔记 > 后端 > 正文

RESTful授权

如何解决《RESTful授权》经验,为你挑选了1个好方法。

我正在Rails中为现实世界组织的成员构建一个基于社区的站点.我正在努力坚持RESTful设计的最佳实践,而且大多数都是或多或少地通过书本.使我的大脑在整洁的RESTful圈子中运行的问题是授权.身份验证是一个容易,长期解决的问题,广泛接受的RESTful解决方案,但RESTful授权似乎有点黑色艺术.我正在尝试找到这样一种方法,它将提供最通用和灵活的框架来控制对资源的访问,同时尽可能简单,同时符合RESTful架构.(还有一匹小马.)

注意事项:

    我需要控制对各种资源的访问,例如用户,页面,帖子等等.

    对于给定资源的授权必须比简单CRUD更精细.

    我希望允许自己和他人在应用程序中编辑授权规则.

    应允许授权规则依赖于谓词,例如(概念上)所有者(用户,资源)或锁定(主题)

考虑(2)是最让我担忧的问题.在我的权限概念和RESTful动作概念之间似乎存在阻抗不匹配.例如,选择帖子(如留言板).REST指示在Post资源上存在四个操作:创建,读取,更新和删除.很容易说用户应该能够更新自己的帖子,但只允许某些用户(或角色或组)锁定它们.表示锁定的传统方式在Post的状态内,但是这会导致在相同条件下的用户可能或可能无法根据他提供的(完全有效)值更新帖子的气味.对我来说,似乎有两种不同的行动来改变邮政的状态,

(我应该注意,这个问题与由于无效或不一致的数据导致更新失败的问题截然不同- 来自非特权用户的锁定请求原则上非常有效,简单地不允许.)

腐烂不是分解另一个词吗?

这可以通过分解Post来克服:一个Lock是一个特定帖子的子资源,而Create或Destroy一个可能具有单独的权限.这个解决方案具有REST环,但它带来了理论和实践方面的困难.如果我将锁定分解出来,那么其他属性呢?假设我完全决定只允许一名管理员修改帖子的标题?然后,授权的简单更改需要重组数据库以适应它!这不是一个解决方案.为了在分解策略下允许这种灵活性,需要每个属性都是资源.这有点进退两难.我的隐含假设是资源在数据库中表示为表.在这个假设下,每个属性的资源表示每个属性的表.显然,这是不切实际的.但是,要消除这种假设会导致表和资源之间的阻抗不匹配,这可能会打开它自己的蠕虫病毒.使用这种方法需要比我给出的更深入的考虑.一方面,用户合理地希望能够一次编辑多个属性.请求在哪里?到包含所有属性的最小资源?并行地对每个单独的资源?到月球?使用这种方法需要比我给出的更深入的考虑.一方面,用户合理地希望能够一次编辑多个属性.请求在哪里?到包含所有属性的最小资源?并行地对每个单独的资源?到月球?使用这种方法需要比我给出的更深入的考虑.一方面,用户合理地希望能够一次编辑多个属性.请求在哪里?到包含所有属性的最小资源?并行地对每个单独的资源?到月球?

其中一些东西不像其他东西......

假设我没有分解属性.然后,替代方案似乎是为每个资源定义一组权限.然而,在这一点上,REST的同质性已经丧失.为了定义资源的访问规则,系统必须具有该资源功能的特定知识.此外,现在不可能一般地将权限传播给后代资源 - 即使子资源具有相同名称的特权,特权之间也没有固有的语义连接.在我看来,定义类似REST的标准权限集是两个世界中最糟糕的,所以我对每种类型的资源都会遇到单独的权限层次结构.

好吧,我们做了鼻子.还有帽子.但这是一种资源!

我看到的一个建议减轻了上述方法的一些缺点,即将权限定义为资源上的create/delete 和属性的读/写.该系统是属性 - 资源和每资源特权之间的折衷:一个仍然只有CRUD,但为了授权,读取和更新属于属性,可以将其视为伪资源.这提供了属性 - 资源方法的许多实际好处,尽管概念完整性在某种程度上受到了损害.权限仍然可以从资源传播到资源,从资源传播到伪资源,但绝不会从伪资源传播.我还没有充分探讨这一战略的后果,但似乎它似乎很有希望.在我看来,这样的系统最适合作为模型的组成部分.例如,在Rails中,它可能是一个改进版ActiveRecord.这对我来说似乎相当激烈,但授权是如此根本的交叉关注,这可能是合理的.

哦,不要忘记小马

所有这些都忽略了预测权限的问题.显然,用户应该能够编辑自己的帖子,但没有其他人的帖子.同样显然,管理员编写的权限表不应该为每个用户分别记录.这几乎不是一个罕见的要求 - 诀窍是使它成为通用的.我认为我所需要的所有功能都可以通过仅使规则具有预测性来获得,从而可以快速且立即地确定规则的适用性.规则" allow User write Post where Author(User, Post)"将转换为" for all User, Post such that Author(User, Post), allow User write Post"和" deny all write Post where Locked(Post)"转换为" for all Post such that Locked(Post), deny all write Post".(这将是伟大的如果所有这些谓词都可以用一个用户和一个资源来表达.)概念上得出的"最终"规则将是非预测性的.这提出了如何实现这样一个系统的问题.谓词应该是Model类的成员,但我不确定如何在规则的上下文中优雅地引用它们.要安全地这样做需要某种反思.在这里我再次感觉这将需要改进Model实现.

你怎么拼这个呢?

最后一个问题是如何最好地将这些授权规则表示为数据.数据库表可能有这个技巧,enum列为allow/deny和C/R/U/D(或者可能是CRUD位?或者可能是{C,R,U,D}×{允许,拒绝,继承}?) ,以及包含路径的资源列.也许,作为一种方便,一个"继承"位.就谓词而言,我很茫然.单独的桌子?当然有很多缓存可以防止它过于缓慢.


我想这要求很多.在提出这个问题之前我曾尝试过做作业,但此时我真的需要一个外在的视角.我很感激任何你可能对这个问题的任何意见.



1> Darrel Mille..:

对不起,我没有时间做正义的这个问题,但很高兴看到一些经过深思熟虑的问题.以下是一些评论:

不要陷入将HTTP谓词映射到CRUD的陷阱.是GET和DELETE映射非常干净,但PUT可以执行创建和更新(但仅完全替换),POST是通配符动词.POST实际上是处理不适合GET,PUT和DELETE的所有内容.

使用属性来表示对象的状态只是一种状态管理方法.我猜您可以想象以下请求可能会做什么:

POST /LockedPosts?url=/Post/2010

子资源也是管理资源当前状态的有效方法.我不觉得有必要以一致的方式处理资源的"状态"属性及其"数据"属性.

尝试将资源直接映射到表格会严重限制您.不要忘记,当您遵循REST约束时,您可以使用的动词突然非常有限.您需要能够在您使用的资源中创造性地弥补这一点.将自己限制为一个资源等于一个表将严重限制最终应用程序的功能.

我们经常看到Rails,ASP.NET MVC和WCF Rest用户在StackOverflow上发布关于如何在REST约束下做某些事情的问题.问题通常不是REST的约束,而是框架在支持RESTful应用程序方面的局限性.我认为首先找到问题的RESTful解决方案然后看看是否可以映射回您选择的框架是至关重要的.

至于创建一个存在于比资源本身更细粒度的权限模型.请记住,其中一个关键的REST约束是超媒体.超媒体不仅可用于查找相关实体,还可用于表示有效/允许的状态转换.如果返回包含嵌入式链接的表示,有条件地基于权限,则可以控制谁可以执行哪些操作.即如果用户有权解锁POST 342,那么您可以返回嵌入在表示中的以下链接:


如果他们没有该权限,则不要返回该链接.

我认为你在这里遇到的一个困难就是你要立刻咀嚼太大的问题.我认为您需要查看您尝试向客户端公开的RESTful接口,作为管理权限和谓词的一个明显问题,以便管理域模型中的授权.

我意识到我没有直接回答你的任何问题,但希望我提供了一些可能在某种程度上有所帮助的观点.

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有