对于MongoEngineResource的嵌入字段的请求,如果它包含引用字段,则不会通过身份验证过程。
我的情况如下:
embedded_section
(可选),该科其中的引用,并且存在不包括自参照(例如embedded_section只能参照部,其不包含FieldDefinition)信号LI>
以下是代码:
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 /部分/ 524df40502c8f109b07ed6ae /),一切都顺利,并正在在存在和不存在的两种情况下正确地显示fields
ATTR embedded_section
。
但尝试引用特定字段(例如/ api / v1 / section / 524df40502c8f109b07ed6ae / fields / 0 /)会引发错误:
error_message: "'AnonymousUser' object has no attribute 'has_permission'"
has_permission是MongoUser的一种方法,它继承自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'
"}
答案 0 :(得分:0)
这是django-tastypie-mongoengine中的一个已知问题:见 https://github.com/wlanslovenija/django-tastypie-mongoengine/issues/71
https://github.com/wlanslovenija/django-tastypie-mongoengine/issues/72
和https://github.com/wlanslovenija/django-tastypie-mongoengine/issues/70
这三个问题存在同样的问题:
身份验证仅在操作本身之前执行,而不是在目标操作之前对资源执行操作之前执行。
示例(使用我的问题中的代码):FieldDefinitionResource实例的目标操作update_detail
,它是SectionResource的子代。在更新FieldDefinitionResource的详细信息之前,有一个read_detail
的SectionResource - 这是一个动作,django-tastypie-mongoengine会跳过Authentication阶段。这导致缺少request.user,这反过来又阻止了工作流向目标操作移动(子资源的update_detail)。
这适用于EmbeddedDocumentField,EmbeddedListField,ReferencedListField和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!'))
但是,当然,在将来的版本中解决它会很好。