0

MongoEngineResource の埋め込みフィールドへのリクエストは、参照フィールドを含む場合、認証プロセスを経由しません。

私の場合は次のとおりです。

  • FieldDefinitions で構成されるドキュメント セクションがあります。
  • FieldDefinitions は EmbeddedDocuments です
  • FieldDefinition にembedded_sectionはセクションを参照する (オプション) が含まれており、自己参照を除外するシグナルがあります (たとえば、embedded_section は FieldDefinition を含まないセクションのみを参照できます)。
  • これはすべてモデレーターのインターフェースの一部であるため、あらゆる種類のリクエスト (取得、投稿、パッチなど) に対して承認を使用します。

コードは次のとおりです。

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/) を要求すると、すべてがスムーズに進み、fieldsattr は の有無にかかわらず正しく表示されますembedded_section

ただし、特定のフィールド (例: /api/v1/section/524df40502c8f109b07ed6ae/fields/0/) を参照しようとすると、エラーがスローされます。

error_message: "'AnonymousUser' object has no attribute 'has_permission'"

has_permission は Django auth.User を継承した MongoUser のメソッドです。説明されている最初のケース (セクションの詳細) では、認証を通過し、request.user に適切なユーザー オブジェクトを入力しますが、2 番目のケース (セクション フィールド) では、認証ステージを完全にスキップし、承認に直接進みます。

私は何か間違ったことをしていますか?

完全なトレースバックは次のとおりです。

{"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'
"}
4

1 に答える 1

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

これらの 3 つの問題は、同じ問題に関するものです。

認証はアクション自体の前にのみ実行されますが、ターゲット アクションの前のリソースに対するアクションの前には実行されません。

例 (私の質問のコードを使用): update_detailSectionResource の子である FieldDefinitionResource のインスタンスのターゲット アクション。FieldDefinitionResource の詳細を更新する前に、SectionResource があります。read_detailこれは、django-tastypie-mongoengine が認証ステージをスキップするアクションです。その結果、request.user がなくなり、ワークフローがターゲット アクション (子リソースの update_detail) に移動できなくなります。

これは、EmbeddedDocumentField、EmbeddedListField、ReferencedListField、および ReferenceField に適用されます。

考えられる回避策の 1 つは、埋め込み/参照ドキュメントの承認をオーバーライドすることです。

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!'))

もちろん、将来のリリースで解決されるとよいでしょう。

于 2014-01-15T12:50:08.010 に答える