Django-tastypie: 需要一个更安全的默认值:DjangoAuthorization应该不允许对所有模型对象的read访问。

创建于 2016-01-06  ·  10评论  ·  资料来源: django-tastypie/django-tastypie

查看tastypie/authorization.py (大约是133-2016年1/4的主分支),默认情况下, read_listread_details绕过user.has_perm()支票,这是非常不安全的,而且是默认设置。

Django的Admin默认为非常规。 因此,我可以看到它是如何被误解的。

https://docs.djangoproject.com/es/1.9/topics/auth/default/#permissions -and-authorization

The Django admin site uses permissions as follows:
*   ... 
* Access to view the change list, view the “change” form and change an object is limited to users with the “change” permission for that type of object.

本质上,“ change_xyz”是“读取”和“更新”的权限代码。 我认为更好的默认设置是遵循Django的Admin:

diff --git a/tastypie/authorization.py b/tastypie/authorization.py
index 1d6f5aa..44b2d56 100644
--- a/tastypie/authorization.py
+++ b/tastypie/authorization.py
@@ -151,22 +151,14 @@ class DjangoAuthorization(Authorization):
         return model_klass

     def read_list(self, object_list, bundle):
-        klass = self.base_checks(bundle.request, object_list.model)
-
-        if klass is False:
-            return []
+        # By default, follows `ModelAdmin` "convention" to use `app.change_model`
+        # `django.contrib.auth.models.Permission` for both viewing and updating.
+        # https://docs.djangoproject.com/es/1.9/topics/auth/default/#permissions-and-authorization

-        # GET-style methods are always allowed.
-        return object_list
+        return self.update_list(object_list, bundle)

     def read_detail(self, object_list, bundle):
-        klass = self.base_checks(bundle.request, bundle.obj.__class__)
-
-        if klass is False:
-            raise Unauthorized("You are not allowed to access that resource.")
-
-        # GET-style methods are always allowed.
-        return True
+        return self.update_detail(object_list, bundle)

bug immediate

最有用的评论

当您进行影响生产的更改时,至少可以在版本控制中反映出来吗?
Deliciouspie的x.y.z版本非常像大多数人期望的那样,通常是:

给定版本号MAJOR.MINOR.PATCH,增加:
..
进行向后兼容的错误修复时的PATCH版本。

在新的生产部署过程中,我花了一个非常不舒服的时间来跟踪此问题。

所有10条评论

我很欣赏这已经合并,但是我仍然对此表示怀疑。 在打开新请求之前,我要担心的是:

不幸的是,此更改破坏了现有代码,因此向后不兼容(以前,所有GET请求都将通过DjangoAuthorization)。 要修复自己的代码,仅有的两个选择是为所有用户授予“更改”权限(不好),或者为DjangoAuthorization子类化以实现读取动作的自定义实现(可能需要大量工作)。 这是故意的吗?

我赞赏在django管理员上下文中进行此操作的原因,但我怀疑在API上下文中将“读取”设置为等效于“更改”是否是明智的默认假设,因为这不是预期的行为。 毕竟,如果GET是与DjangoAuthorization一起使用的允许方法,为什么会基于用户没有change许可的事实拒绝访问?

我建议他采用以下替代实施:

_对于read_detail_

  • 如果模型具有view权限,请检查(=改进那些需要它的人)
  • 如果没有view权限,则始终允许(=向后兼容)

_用于阅读列表_

  • 如果模型具有list权限,请检查(=改进那些需要它的人)
  • 如果没有list权限,则始终允许(=向后兼容)

通过这种方式,asteapie添加了一个与Django权限默认值兼容的默认值,同时为需要的人添加了查看和列表权限,从而提供了一条轻松的途径来进行改进,而无需编写DjangoAuthorization的自定义实现。

至少应该有一种方法可以指定默认权限:

DjangoAuthorization(read_permission='view', # applies to both list, detail if not spec'd
                    read_list_permission='view', # list only
                    read_detail_permission='view') # detail only
# while we're at it, why not add the other permissions too
DjangoAuthorization(change_permission='change',
                    delete_permission='delete',
                    add_permission='add', 
                    # ... add options as per above for each
                    # <action>_<level> permission where 
                    # action is `change,delete,add,read`,  level is `list,detail`)

@SeanHayes将是决定的人。

仅在这里,我认为默认情况下允许读取是一个安全问题。 在完全接近生产之前,我完全没想到这一点。 我认为在这种情况下有必要打破向后兼容。

看起来您的建议需要将参数传递给现有代码DjangoAuthorization ,在这种情况下,我认为将类称为其他名称会更清楚。

考虑read_permission='view'情况,这可能正是您所需要的。 我不明白为什么它不如最佳

class ModifiedDjangoAuthorization(DjangoAuthorization):
    READ_PERM_CODE = 'view'

如果您想更改其他,只需覆盖方法即可。 所做的更改实际上是为了使其变得非常容易而设计的。

class ModifiedDjangoAuthorization(DjangoAuthorization):
    def delete_list(self, object_list, bundle):
        return self.perm_list_checks(bundle.request, 'del', object_list)

    def delete_detail(self, object_list, bundle):
        return self.perm_obj_checks(bundle.request, 'del', bundle.obj)

所做的更改确实考虑了修改并使其变得容易。 我没有必要认为它应该作为init参数来完成。

我认为默认情况下允许读取是一个安全问题。

我没有质疑原始问题的意图。 只是指出合并的实现破坏了人们现有的代码和假设,而没有这样说,并且没有有效的还原方法。

看起来您的建议需要将传递给DjangoAuthorization的参数更改为现有代码,

如果您再次查看我提出的解决方案,那么我提倡的是为人们提供安全且向后兼容的默认选项。 在这种情况下,无需更改用户代码。

我认为在这种情况下有必要打破向后兼容。

我不同意。 当前合并的更改不仅打破了向后兼容的功能,而且还引入了更大的潜在安全问题,显而易见的方式(由当前实现暗示)是将更改权限分配给应允许GET的所有用户。

坦白说,我看不到读取操作的change权限如何提高安全性,因为此权限还允许PUT。 混合不同操作的权限似乎不是一个好选择。

不幸的是,除非您实际上向模型添加了view权限,否则您建议的ModifiedDjangoAuthorization将无法解决问题,因此再次破坏了向后兼容性。 至少它需要更改代码-因此我们破坏了向后兼容性,并迫使用户重新设计他们的代码库。

当然,覆盖始终是实现一个人的特定要求的一种选择,但是我认为好吃的一般想法是提供合理且安全的默认值,而无需添加自定义代码...

简而言之,我认为应该更改此更改以更好地实施。

change权限来自Django本身。 这是Django的默认设置,这是设置Django Admin应用程序的方式。 选项view不是。 我个人将我的名字命名为read

通过检查model不确定您的意思。 如果要检查_meta,则可能不完整。 如果您要访问数据库,我发现它不必要地昂贵。

按照我的偏爱,您提出的建议似乎在默认授权的“太多魔术”方面。 只需设置一个安全的默认值(可以轻松覆盖)就足够了。 但那只是我的个人意见。

此处记录了更改: https :

坦白地说,我看不到读取操作的更改权限如何提高安全性,因为此权限还允许PUT。 混合不同操作的权限似乎不是一个好选择。

我们知道,如果用户可以更改某些内容,那么他​​们可以阅读它,这就是Django管理员执行操作的方式。

这个版本更安全,因为它迫使开发人员考虑他们在做什么。 如果开发人员没有发明自己的“读取”权限,而是选择在每个人仅应具有“读取”权限时故意给每个人“更改”权限,那是他们的问题; 我不能阻止其他开发人员故意做愚蠢的事情,我是在这里阻止Tastypie做愚蠢的事情。 进行此更改的目的是为了防止对使用DjangoAuthorization的任何资源进行全局读取权限,而开发人员可能并不希望这样做。 新行为与开发人员在Django管理员中的体验一致。

如果您想要旧的行为:

  1. 不要升级到0.13.2。
  2. 或覆盖read_list and read_detail`方法。

如果您认为文档可以改进,请随时提交PR。

感谢您的反馈。 非常感谢您提供给文档的链接,很公平,我很想念那个链接(请注意,该问题已分配给v0.13.4,而文档位于v0.13.2中)。

让我从我的观点做最后的评论:

我们知道,如果用户可以更改某些内容,那么他​​们可以阅读它,这就是Django管理员执行操作的方式。

Django管理员使用change权限,因为管理界面_is_关于_changing_对象。 在那里有意义。 根据定义,REST API上的GET请求与_reading / viewing_有关。 我想大多数开发人员根本就不会期望DjangoAuthorization基于缺少更改权限而拒绝阅读。

这个版本更安全,因为它迫使开发人员考虑他们在做什么。

最美味的广告功能之一就是提供“合理的默认值”。 假设API的GET(按定义:读取)和PUT(更改)方法在所有意图和目的上都是不同的操作,并且还需要不同的权限,这是否合理?

如果你们认为这是有价值的补充,我很乐意按照我写的内容贡献PR。

更改权限来自Django本身。 (...)选项视图不是。

在Django中有一个待处理的PR添加view permission ,这就是为什么我使用view的原因。

默认情况下,我们将不允许公共/全局读取操作。 到最后了而且,当当前尚无标准方法时,我们不会试图猜测开发者如何设置其权限。 我们甚至不确定是将其称为“已读”还是“查看”,而且我不希望一群人涌入这里说“我这样做”或“新的Django版本将其称为其他”。 。

如果并且当Django支持开箱即用的读取/查看权限时,我们将切换到该权限。 目前,开发人员将只需要编写一些自定义代码来处理他们处理权限的自定义方式。

我知道这个问题已经解决,但是我只想简单地说一下,这一更改基本上使我无法将现有项目迁移到0.13.x。

@miraculixx我认为对于仅要求查看数据的更改权限有点疯狂的事实,您是完全正确的。 我想我们仍然可以以某种方式怪罪Django,但没有查看权限的概念(这让我的观点大打折扣,我认为包含CRUD管理组件的项目根本没有权限允许我发疯。读取部分)。

当您进行影响生产的更改时,至少可以在版本控制中反映出来吗?
Deliciouspie的x.y.z版本非常像大多数人期望的那样,通常是:

给定版本号MAJOR.MINOR.PATCH,增加:
..
进行向后兼容的错误修复时的PATCH版本。

在新的生产部署过程中,我花了一个非常不舒服的时间来跟踪此问题。

此页面是否有帮助?
0 / 5 - 0 等级