django的灵活的每对象授权后端

django-rules的Python项目详细描述


H1(摘要)。django rules

django rules是一个django授权后端,它提供了一个统一的、按对象的授权管理。它与其他授权后端有很大不同,它允许您灵活地管理每个对象的权限。

django规则中的每个规则都会向给定的模型添加授权约束。授权约束将检查给定用户是否符合该约束(例如,用户是否具有对某个对象执行特定操作的正确权限等)。授权约束可以是模型的布尔属性、属性或方法,具体取决于每个规则:)




django rules致力于构建灵活且可扩展的授权后端。为什么它比其他授权后端更好?
*后端简单、简洁、紧凑。更少的代码行意味着更少的复杂性、更快的执行速度和(希望:)更少的错误和bug。
*您可以将每个授权约束实现为模型的布尔属性、属性或方法,无论您对每个规则选择哪个:)这样您就可以随时重新实现授权的工作方式。它是动态的,而且您知道动态声音比静态声音好得多:)
*您不必向用户添加额外的权限或组。您只需根据自己的喜好对约束进行编程,然后将它们分配给规则。完成!
*您可以对规则如何处理身份验证进行精细控制:一个规则可以使用使用LDAP的授权约束,而其他规则则调用Web服务(或任何您希望挂接在授权约束中的内容)。
*其他每个对象的授权后端在表中为每个对象、每个用户和每个权限组合创建一行。即使是一个平均大小的站点,你也会有可伸缩性噩梦,不管你能缓存多少。
*其他授权后端必须选择用户拥有的所有权限,即使你只需要检查一个特定权限,使内存占用更大。
*其他授权后端无法设置集中权限,这在大多数项目中都是必需的。



h2(需求)。要求

django规则要求正确安装django 1.2(至少)。




h3(pypi)。从pypi

操作简单:

<;pre>;
pip install django rules
<;pre>;

h3(source)。从源代码安装django规则:


<;pre>;
git clone https://github.com/maraujop/django rules/
cd django rules
python setup.py install
<;pre>;


h2(配置)。配置

若要使django规则生效,必须将其挂接到项目中:

*将其添加到<;code>;settings.py<;/code>;中已安装的应用程序列表中:

已安装的应用程序=(

"django规则",

<;/pre>;

*将django规则授权后端添加到<;code>;设置中的<;代码>;身份验证后端<;代码>;列表中:


<;pre>;
身份验证后端=(
"django.contrib.auth.backend.modelbackend",#django的默认身份验证后端
"django_rules.backend s.objectpermissionbackend",

<;pre>;

*运行syncdb以使用新的django规则模型更新数据库:

<;pre>;
python manage.py syncdb
<;pre>;

h2(规则)。规则

规则表示一个功能授权约束,它限制特定用户可以对特定对象(模型实例)执行的操作。

每个规则定义由6个参数组成(3个必需参数和3个可选参数):
*<;code>;app_name<;/代码:应用规则的应用程序的名称。
*<;code>;code name<;code>;:规则的名称,在所有应用程序中唯一。它应该是一个简短而独特的名称。
*<;code>;model<;/code>;:与规则关联的模型的名称。

*<;code>;field\u name<;/code>;(可选)boolean属性的名称,实现授权约束的模型的属性或方法。如果未设置,则默认为必选字段的值<;code>;code name<;/code>;
*<;code>;view_param_pk<;/code>;(可选)要用于获取模型主键的视图参数的名称。它在修饰视图中用于获取模型的实际实例,即检查授权的对象。如果未设置,则默认为模型中主键字段的名称。注意,如果持有对象主键值的视图参数的名称与模型主键的名称不匹配,则必须在该参数中指定新名称(我们将在"decorators"一节中讨论这种特殊情况):"decorators"。
*<;code>;说明<;/code>;(可选)说明说明授权约束的预期行为的简短说明(最多140个字符)。虽然这是可选的,但它被认为是一个良好的实践^tm^,应该始终使用它。

应该为每个django应用程序创建规则。也就是说,在要创建规则的django应用程序的根目录下,应该有一个<;code>;rules.py<;/code>;只包含特定于该django应用程序的那些规则的声明。

规则。py<;/code>;,您将要激活它们。对于每个要激活的规则,您*必须*通过调用<;code>;django_rules.utils为其添加注册点。在<;code>;rules.py中注册<;code>;

您需要将规则同步到数据库。在Django项目中,您必须运行"sync_rules"命令:


<;pre>;
python manage.py sync_rules
<;pre>;

>此命令将查找您安装的应用程序下的所有<;code>;规则。将最新更改同步到数据库,因此您根本不必运行<;code>;syncdb<;/code>;或重新生成完整的数据库。



h2(示例)。示例:



h3(ex1)。示例1:在"shipping"django应用程序中为项目模型创建一个简单、紧凑的规则


类项(models.model):
supplier=models.foreignkey(user)
description=models.charfield(max_length=50)
<;/pre>;

由供应商发货"。现在,为了遵守功能授权约束,我们只需要创建一个简单的规则。

首先,让我们从向项目模型添加授权约束开始。请记住,我们可以使用方法、布尔属性或布尔返回属性。这次我们将使用一种方法:

<;pre>;
类项目(models.model):
supplier=models.foreignkey(user)
description=models.charfield(max_length=50)

def可以装运(self,用户obj):
"
"检查给定用户obj是否是项的供应商
"
返回self.supplier==用户obj
<;/pre>;

e在应用程序的<;code>;rule s.py<;/code>;文件中:

<;pre>;
from django_rules import utils


rules_list=[
{codename':'can撸ship','model':'item'},

注意:
总是添加可选的"说明"字段是
良好做法^tm^,以便对规则的预期行为进行简要解释。



要使规则处于活动状态,我们*必须*注册它们:
规则列表中的规则:
utils.register(app撸name="shipping",**规则)
<;pre>;

最后,不要忘记同步规则,以确保所有新定义、更改等都同步到数据库。

<;pre>;
python manage.py sync_rules
<;pre>;


h3(ex2)。示例2:创建一个不遵循命名约定的规则

例如,让我们更改以前的项模型:

<;pre>;
类项(model s.model):
supplier=models.foreignkey(user)
description=models.charfield(max_length=50)

def issameSupplier(self,user_obj):\更改授权约束的名称约定
"
"检查给定的用户obj是否是项的供应商
"
返回self.supplier==用户obj
<;/pre>;

,我们必须在应用程序的<;code>;rule s.py<;code>;文件中使用附加的可选字段来设置更详细的规则。这一次,只需要<;code>;字段名<;/code>;,但最好是^tm^简要介绍<;code>;说明<;/code>;:

<;pre>;
来自django规则导入实用程序

rules\list=[
代码名:'可以发货','型号':'项目','字段名':'isSameSupplier',
'说明':'检查给定用户是否为项目的供应商'},
]


不要忘记同步规则,以确保所有新定义、更改等都应用于数据库。

<;pre>;
python manage.py sync_rules
<;pre>;



h3。使用规则

一旦设置了实现功能授权约束的规则,就可以(而且应该:)在应用程序中使用它。真的很简单!在每个要对用户强制授权约束的地方,您只需进行以下调用:

<;pre>;
user_obj.has_perm(codename,model_obj)
<;
数据库中的数据(至少一个供应商和一个项目,两个ID都等于1)。请记住,我们已经实现、定义、注册并同步了以下规则:

<;pre>;
{'codename':'can'u ship'、'model':'item'}
<;pre>;

我们只需要执行以下操作来执行规则:

<;pre>;
supplier=supplier.objects.get(pk=1)
item=item.objects.get(pk=1)

供应商可以发货!:)'
<;pre>;

简单,对吧?:)



h4.有关django规则内部魔力的详细信息,请注意下面是django规则中所有内部魔力如何流动的详细说明。如果你真的不在乎,请走开。你真的不需要这些细节就能有效地编写规则和使用django规则。但是,如果您有兴趣并想了解更多,请注意下面的细节。

这个难题集中在一起:
*当您调用<;code>;user_obj.has_perm(codename,model_obj)<;/code>;(在前面的示例中,<;code>;supplier.has_perm('can_ship',item)<;/code>;)时,django将处理对django规则后端的控制。
*然后django规则后端将尝试将代码名与规则匹配。请注意,我们正在请求一个规则,该规则的代码名为"Can'u Ship"(可以发货)的代码名为"of"(可以发货)的代码名为"Can'u Ship"(可以发货)的代码名为"of"(可以发货)的代码名为"Can'u Ship"(可以发货)的代码名为"Can'u Ship"(可以发货)的代码名为"Can't"(可以发货)的代码名为"Can'u Obj"(可以发货)的代码名为"Can因为在"示例1":"ex1"中,我们定义了规则<;code>;{'code name':'can'u ship','model':'item'}<;/code>;,将有一个匹配项。
*然后,django规则将检查<;code>;字段"name"<;/code>;是属性、属性还是方法,并将相应地执行操作。如果<;code>;字段名<;/code>;是一个方法,django规则后端将检查它是否只需要一个用户参数或根本不需要参数。根据参数要求,它将执行<;code>;model_obj.field_name()<;/code>;或<;code>;model_obj.field_name(user_obj)<;/code>;。在我们的"示例1":ex1中,我们需要一个用户参数,这样它将执行<;code>;item.can掼ship(supplier)<;/code>;
*最后,如果在<;code>;field掼name<;/code>;中实现的授权约束为true或返回true,则认为该约束已实现。否则,您将无法获得授权。



h3。如我们所见,django规则将检查<;code>;字段名<;/code>;是属性、属性还是方法,并相应地执行操作。您可以基于模型的属性和属性创建规则,对于非常简单的情况,这些属性和属性非常好,但大多数情况下,您将设置<;code>;字段名<;/code>;对于模型中的方法,

它不能接收多个参数或不是用户实例的参数。虽然这看起来像是一个限制,但我们无法考虑这样一个用例,即不能从用户或模型对象中检索所需的其余信息。如果你遇到这种情况,这是限制你,请联系和解释你的问题,以便我们可以考虑如何绕过它!:)

最后,您需要注意一些非常重要的事情:分配给规则的方法(从现在起我们将其称为规则方法)*不应调用任何其他方法*。也就是说,它们应该是自给自足的。这是为了避免潜在的无限递归。想象一下这样一种情况:rule方法调用的另一个方法具有与前一个rule方法相同的授权约束。繁荣!你刚刚创建了一个无限循环。逃命吧!:)

您可能认为您可以控制这一点,但相信我,维护和扩展将变得非常困难。事情并不总是那么简单,也许你最终会调用一个稍后被修改的方法,并最终调用一个触发相同授权循环的helper函数。是的,我知道。间接是一个婊子:)或者,换句话说,"伟大的力量伴随着伟大的责任"。所以要小心无限循环;)



h2(decorators)。如果你和我一样喜欢python,你就会喜欢decorators。django有一个<;code>;权限必需的装饰器,因此django规则很自然地实现了一个<;code>;对象必需的权限必需的装饰器。



<;pre>;
定义发货项(请求,id):
item=item.objects.get(pk=id)


if request.user.has懔perms('can懔ship',item):
返回httpresponse('success')

return httpresponse('error')
<;/pre>;


我们可以很容易地修饰视图,使该方法更加紧凑和易于阅读:

<;pre>;
来自django规则的import object\u permission\u required

@object\u permission\u required('can\u ship')
def ship\u item(请求,id):
返回httpresponse('项目成功发货!:)')
<;/pre>;

首先,它匹配规则并从中获取模型的类型。然后,它从视图的kwargs中获取<;code>;id<;/code>;参数,并使用<;code>;item=model.object s.get(pk=id)<;/code>;实例化模型对象。最后,它可以为您调用<;code>;request.user.has_perm('can_ship',item)<;/code>;并在未满足约束的情况下重定向到失败页。

如果参数的名称与模型中主键的名称不匹配,请记住,我们必须向规则添加另一个可选参数。从"关于规则的部分:":"规则
*<;代码>;查看参数pk<;/code>;(可选)"中:用于获取模型主键的视图参数的名称。它在修饰视图中用于获取模型的实际实例。如果未设置,则默认为模型中主键字段的名称。请注意,如果保存对象主键值的视图的参数名称与模型的主键名称不匹配,则必须在此参数中指定新名称。

例如,如果修改视图的参数:

<;pre>;
from django_rules import object_permission_required

@object_permission_required('can_ship')
def ship_item(request,my_item_code):-->;更改视图中参数的命名
返回httpresponse('success')
<;/pre>;

我们必须在规则定义中指定<;代码>;查看参数pk<;/code>;

<;pre>;
规则列表=[
{代码名:'可以发货','型号':'项目','查看参数pk':'我的项目代码',
"说明":"检查给定用户是否是项的供应商"},
]
<;/pre>;



return_=true)
@object_permission_required('can_ship',redirect_url='/more/foo/bar/')
@object_permission_required('can_ship',redirect_field_name='myfoofield')
@object permission_required('can_ship',login_url='/foo/bar/')
<;pre>;

return"403"<;/code>;设置为false。
*<;code>;redirect"url"<;/code>;设置为空字符串。
*<;code>;redirect"field"名称<;/code>;设置为django.contrib.auth的redirect"field"名称。
*<;code>;login"url"<;/code>;设置为<;code>;settings.login_url<;/code>;

因此,如果未满足授权约束,装饰器将默认重定向到django样式的登录页:)

即:
*如果<;code>;return"403"<;/code>;设置为true,则它将覆盖其余参数,并且装饰器将返回一个httpresponseforbidden。
*如果<;code>;redirect"url"<;/code>;设置为url,则它将覆盖<;code>;login"url"<;/code>;.当视图方法是通过URL的入口点时(即,如果视图方法直接映射到一个<;code>;url.py<;code>;条目),django将解析URL并将参数作为<;code;传递给视图>;夸尔格斯<;/代码>;。因此,如果要在内部方法(在这些外部视图中的一个或代码中的其他位置调用的方法)上使用需要的对象权限装饰符,则在传递参数时必须使用夸尔斯。

例如:

<;pre>;
def item廑u shipper(请求,id):
内部廑u code='xxx-'+我的廑u item廑u code
返回廑u ship廑u item(请求,id=internal廑u code)而不是执行返回廑u ship廑u item(内部_代码)

@object_permission_required('can_ship')
def_ship_item(request,id)
return httpresponse('success')
<;/pre>;

h2('centralized permissions)。集中式权限

django规则有一个中心授权分派器,它针对实际项目中非常常见的需求:特殊的特权组,如管理员、用户支持人员等,有权覆盖应用程序中授权约束的某些方面的。在这种情况下,Django规则可以让您出于任何原因绕过其授权系统。

在该模块中,您必须定义一个名为"中心授权"的布尔返回函数,该函数只接受两个参数:
*<;code>;用户目标<;/code>;:用户对象。
*<;code>;代码名<;/code>;:将重写的规则的代码名。优化特殊用户"a la acl"的权限非常有用。
请注意,尽管参数的命名并不重要,但顺序确实重要。第一个参数将接收一个用户对象,第二个参数将接收规则的代码名。

this<;code>;central_authorizations()<;/code>;函数将在*任何其他规则之前被调用,因此您可以在此处覆盖所有这些规则。

例如,in<;code>;设置。py<;/code>;您将添加:

<;pre>;
中心授权='myprojectfoo.utils'
<;/pre>;

,然后,在myprojectfoo中,在<;code>;utils.py<;/code>;中,您将实现<;code>;中心授权()<;/code>;使用特殊用户的覆盖功能。

它们是用户支持,因此不能覆盖应用程序中的某些内容。但是,您也希望您的管理员(通常是开发人员)能够访问应用程序中的任何内容,以便他们能够在开发时快速进行编码和测试。

在这种情况下,您可以编写以下<;code>;central_authorizations()<;/code>;函数:

<;pre>;
def central_authorizations(user_obj,codename):
"
此函数将在*任何其他规则之前被调用,
这样您就可以覆盖这里的所有权限。
"
如果用户obj.get戋profile().isuberadmin():
如果用户obj.get戋profile().isusersupport()中的isauthorized=true,则可以覆盖

elif user戋obj.get戋profile().isusersupport()和代码名,'可以删除'u item']:
isauthorized=true

return isauthorized
<;pre>;

状态和测试

django规则是一个安全应用程序。因此,它经过了彻底的测试。它附带了一组测试,试图覆盖所有可用的功能。但是,如果你遇到一个错误或不规则的情况Ion,可以通过"Github Bug Tracker"来报告它:https://github.com/maraujop/django rules/issues。

最后,应用程序附带了许多不同的异常,这些异常将确保正确创建规则。它们的目的还在于保护您的申请安全,避免疏忽大意。明智地管理异常,你将是一个快乐和安全的编码者,因为安全是远离可能的负许可证。你应该小心地管理他们。测试django规则

要运行测试,请进入测试目录并执行:

<;pre>;
./run tests.py
<;pre>;

如果没有,我希望您很快会报告一个损坏的测试:)



h2。需要更多的例子吗?

我已经尽力解释了django规则背后的概念,但是,如果您愿意看更多的代码示例,我相信您会发现"测试中的代码":https://github.com/maraujop/django-rules/blob/master/django-rules/tests/test_core.py相当有用:)


h2。更多文档

以防您想知道所有这些"django中的每个对象身份验证后端"都出现在哪里,您至少应该阅读以下链接:
*一篇关于"django中的每个对象权限后端"的很棒的文章:http://djangoavent.com/1.2/object-permissions/作者florian apolloner
*还有,最后,查看修复"django ticket 11010"时引入的更改的说明:http://code.djangoproject.com/ticket/11010

,我最诚挚的感谢所有为django开发框架做出贡献的人,以及在他们帮助下构建django规则的其他开发人员和提交者。尊敬!:)

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java HttpServletResponse在保存时提示输入文件名   基于Java中的XML值重新创建XML   Java中递归调用的一个堆栈占用多少内存?   java数字到二进制到零计数器   java Primefaces选项卡视图:在计数后设置活动索引   xml在Java中可以将XSD转换为XPath吗?   在递归循环中检测JDBC连接的java插件/工具   spring mvc中的java处理错误   java向spring安全认证添加子域   在安卓中设置时,java日期不正确   java setColorFilter适用于所有按钮   java Android:Bitmap-to-Byte数组和back:SkImageDecoder::Factory返回null   java如何使用lambda实现ComponentScan的自定义过滤器?   java iOS推送通知不工作   java在异步servlet中用新请求替换旧请求