在相关字段上使用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
然后,
请注意,我在allowed_methods,验证等方面有相同的行为。 这种行为对我来说是一种负担,因为它迫使我在任何地方删除full = true以避免安全漏洞。
我做错了什么?
答案 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以及请求并在那里测试授权,但我认为它对于我们期望的奇怪行为变得越来越复杂(两个非常耦合的资源的不同身份验证模型)