为什么full = true会破坏Django Tastypie中的资源行为?

时间:2014-04-07 10:13:30

标签: python django tastypie

在相关字段上使用full=true是非常方便的功能,可以防止客户端做太多请求以获取必要的信息。

尽管如此,我真的不明白为什么一旦使用相关字段就不会遵循Meta Class中的“指令”。

这是一个简单的例子:

class UserResource(ModelResource):
    class meta():
        queryset = User.objects.all()
        resource_name = 'users'
        authorization = NothingAuthorization() # Returns None or [] on GET requests

class ClientUserResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user', full=True)

    class meta():
        queryset = ClientUser.objects.all()
        resource_name = 'client_users'
        # Some other required fields

然后,

  • / users / 1上的GET请求返回401响应(正如预期的那样,完美!)
  • / client_users / 1上的GET请求(client_user 1与用户1相关)返回client_user 1 AND 的数据用户1的数据(我不希望获得用户1的信息)因为它是未经授权的。)

请注意,我在allowed_methods,验证等方面有相同的行为。 这种行为对我来说是一种负担,因为它迫使我在任何地方删除full = true以避免安全漏洞。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

在这种情况下,你对Tastypie的期望是什么?我想您希望看到401 Unauthorized到您的ClientUserResource GET,但在我看来,这将是相当不一致的。您指定ClientUserResource没有定义明确的授权(因此免费GET访问),但是根据您的逻辑,您希望根据其他资源的授权查看响应。

如果你想避免安全漏洞,最好不要使用full = True。你可以根据你想要的规则覆盖水合物方法以返回扩展对象,或者为ClientUserResource使用类似的Authentication类,它考虑到UserResource的规则(在这种情况下,full = True就可以了,因为你正在控制完整的资源访问)。

编辑:我提出了两个更详细的解决方案。

<强> 1。相同授权

我的意思是,如果你想在使用 full = True 时保护你的相关资源,你应该在两个资源中使用相同的授权(或者在ClientUserResource中使用更严格的授权,这样你的UserResource永远不会泄露)。实际上,我想不出一个案例,你希望有两个完全不同的授权逻辑,然后将一个资源包含在另一个资源中。

在您的示例中,您应该添加authorization = NothingAuthorization()。如果你真的想要第二个类的不同认证行为,让我们看看另一个选项。

<强> 2。覆盖脱水方法或obj_create

在这种情况下,您应该删除 full = True 并自行提供该行为,例如覆盖脱水方法。在此方法中,您可以访问您的请求和数据,以便执行某些逻辑。

class ClientUserResource(ModelResource):

    class meta():
        queryset = ClientUser.objects.all()
        resource_name = 'client_users'

    def dehydrate(self, bundle):
        # Do whatever you want, for instance, authorize only one user, and then add
        # to the result your desired info as full=True would do
        if bundle.request.user.username == "admin":
            bundle.data['user'] = {'username': "admin",
                                   'email': "admin@gmail.com", 
                                   ...}}
        return bundle

这可能看起来有点“丑陋”,因为您没有在提供授权逻辑的资源中使用任何Authorization类。我想你可以在脱水方法中建立一个UserResource以及请求并在那里测试授权,但我认为它对于我们期望的奇怪行为变得越来越复杂(两个非常耦合的资源的不同身份验证模型)