Django MongoEngineeResource与ReferenceField的身份验证失败

Django MongoEngineeResource与ReferenceField的身份验证失败,django,mongoengine,tastypie,Django,Mongoengine,Tastypie,如果MongoEngineeResource的嵌入式字段包含引用字段,则对该字段的请求不会经过身份验证过程 我的情况如下: 有一个文档部分,由字段定义组成 字段定义是嵌入的文档 FieldDefinition包含引用节的嵌入式节(可选),并且有一个排除自引用的信号(例如,嵌入式节只能引用不包含FieldDefinition的节) 这一切都是版主界面的一部分,所以我对各种请求(get、post、补丁等)使用授权 代码如下: from tastypie_mongoengine.resources

如果MongoEngineeResource的嵌入式字段包含引用字段,则对该字段的请求不会经过身份验证过程

我的情况如下:

  • 有一个文档部分,由字段定义组成
  • 字段定义是嵌入的文档
  • FieldDefinition包含引用节的
    嵌入式节(可选),并且有一个排除自引用的信号(例如,嵌入式节只能引用不包含FieldDefinition的节)
  • 这一切都是版主界面的一部分,所以我对各种请求(get、post、补丁等)使用授权
代码如下:

from tastypie_mongoengine.resources import MongoEngineResource
from tastypie.authentication import ApiKeyAuthentication
from apps.api.auth import CustomAuthorization

class FieldDefinitionResource(MongoEngineResource):
    embedded_section = ReferenceField(attribute='embedded_section',
                                      to='myproject.apps.api.resources.SectionResource',
                                      full=True, null=True)

    class Meta:
        object_class = models.FieldDefinition # mongoengine EmbeddedDocument
        authentication = ApiKeyAuthentication()
        authorization = CustomAuthorization()

class SectionResource(MongoEngineResource):
    fields = EmbeddedListField(attribute='fields',
                               of='myproject.apps.api.resources.FieldDefinitionResource',
                               full=True, null=True)
    class Meta:
        object_class = models.Section # mongoengine Document
        authentication = ApiKeyAuthentication()
        authorization = CustomAuthorization()
因此,当我询问部分细节(例如/api/v1/Section/524df40502c8f109b07ed6ae/)时,一切都很顺利,
字段
attr在存在和不存在
嵌入部分
的情况下都能正确显示

但尝试引用特定字段(例如/api/v1/section/524df40502c8f109b07ed6ae/fields/0/)会引发错误:

error_message: "'AnonymousUser' object has no attribute 'has_permission'"
has_permission是Mongoser的一种方法,它继承自Django auth.User。在所描述的第一种情况下(部分详细信息),它会通过身份验证并使用适当的用户对象填充request.user,而在第二种情况下(部分字段),它会完全跳过身份验证阶段,直接进入授权

我做错什么了吗

以下是完整的回溯:

{"error_message": "'AnonymousUser' object has no attribute 'has_permission'", "traceback": "Traceback (most recent call last):

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie/resources.py", line 195, in wrapper
    response = callback(request, *args, **kwargs)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie_mongoengine/resources.py", line 277, in dispatch_subresource
    return resource.dispatch(request=request, **kwargs)

  File "/vagrant/myproject/myproject/apps/api/resources.py", line 248, in dispatch
    super(FieldDefinitionResource, self).dispatch(request_type, request, **kwargs)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie_mongoengine/resources.py", line 776, in dispatch
    self.instance = self._safe_get(bundle, **kwargs)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie_mongoengine/resources.py", line 768, in _safe_get
    return self.parent.cached_obj_get(bundle=bundle, **filters)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie/resources.py", line 1113, in cached_obj_get
    cached_bundle = self.obj_get(bundle=bundle, **kwargs)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie_mongoengine/resources.py", line 528, in obj_get
    return super(MongoEngineResource, self).obj_get(bundle=bundle, **kwargs)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie/resources.py", line 2069, in obj_get
    self.authorized_read_detail(object_list, bundle)

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/tastypie/resources.py", line 589, in authorized_read_detail
    auth_result = self._meta.authorization.read_detail(object_list, bundle)

  File "/vagrant/myproject/myproject/apps/api/auth.py", line 201, in read_detail
    bundle.request.user.has_permission('read_detail',

  File "/var/www/vhosts/myproject/local/lib/python2.7/site-packages/django/utils/functional.py", line 205, in inner
    return func(self._wrapped, *args)

AttributeError: 'AnonymousUser' object has no attribute 'has_permission'
"}

这是django tastypie mongoengine中的一个已知问题:参见

这三个问题是关于同一个问题的:

身份验证仅在操作本身之前执行,而不是在目标操作之前对资源执行操作之前执行

示例(使用我问题中的代码):FieldDefinitionResource实例的目标操作
update_detail
,它是SectionResource的子级。在更新FieldDefinitionResource的详细信息之前,有一个SectionResource的
read\u detail
——这是一个动作,django tastypie mongoengine跳过了验证阶段。它会导致缺少request.user,这反过来又会阻止工作流向目标操作移动(更新子资源的详细信息)

这适用于EmbeddedDocumentField、EmbeddedListField、ReferenceListField和ReferenceField

一种可能的解决方法是覆盖嵌入/引用文档的授权:

class CustomAuthorization(Authorization):
    def read_detail(self, object_list, bundle):

        # Double-check anonymous users, because operations
        # on embedded fields do not pass through authentication.
        if bundle.request.user.is_anonymous():
            MyAuthentication().is_authenticated(bundle.request)

        # Now authorize.
        try:
            return bundle.request.user.has_permission(object_list, 'read_detail')
        except AttributeError:
            raise Unauthorized(_('You have to authenticate first!'))

但当然,在未来的版本中解决它会很好。

(有问题的包的维护者):请通过测试提出拉取请求。我本人仅将该包用于公共只读API,因此身份验证完全未经测试,也未得到充分开发。如您所见::-)