2014-08-29 102 views
3

我在Rails中使用了cancan gem,但这可能比这更普遍。应用程序逻辑与授权

简短介绍。在cancan,你定义授权这样的:

can :read, Post 
can :manage, Post if user.is_admin? 
can :manage, Post do |post| post.author == user end 

这意味着,任何人都可以阅读Post S,但只有作者和管理员可以管理(编辑/销毁)他们。

现在我想更改我的应用程序逻辑,以便如果它有任何评论(除非您是管理员),则不能删除您的帖子。它仍然易于使用(添加在上面代码的结尾)cancan

cannot :destroy, Post do |post| post.comments.count > 0 && !user.is_admin? end 

,这意味着我可以使用下面的伪码的视图(HTML模板):

<h1><%=post.title%></h1> 
<p><%=post.text%></p> 
<%=link_to 'Edit', edit_post_path(post) if can? :edit, post%> 
<%=link_to 'Delete', delete_post_path(post) if can? :destroy, post%> 

我唯一的问题是将权限本身与应用逻辑混合起来是否合理?感觉那种肮脏的,但另一方面我需要打破干燥,与应用程序中到处重复检查(前端,API等)

<h1><%=post.title%></h1> 
<p><%=post.text%></p> 
<%=link_to 'Edit', edit_post_path(post) if post.can_be_edited? && can? :edit, post%> 
<%=link_to 'Delete', delete_post_path(post) if post.can_be_destroyed? && can? :destroy, post %> 

回答

1

我看不出有任何问题,替换该将与授权相关行为的检查放在您建议的地方。正如你所提到的,替代方案更糟糕。此外,这意味着某人可以轻松查看一个地点以查看Post的授权方案,这非常可取。另一种方法(在多个地方进行检查)更难以维护和推理,更不用说更改必须在多个地方进行编辑,并且只是开发人员同时编辑它们的一个“绅士协议”,可以使它们保持一致同步中。

0

除了tmruss的评论,我想补充一点,你正在尝试使用cancan称为外部化授权。这是一个很好的方法。您应该始终努力将授权逻辑与业务逻辑分离。

最后最重要的是你在相关的地方做检查。如果你不知道这些相关的地方是什么,那么你需要回到应用程序的绘图板来确定所有入口点。这些入口点是您想要应用细粒度授权/ cancan的位置。

查看XACML reference architecture了解正式架构概述。