【问题标题】:django tastypie REST query filtering based on authorised user基于授权用户的django tastepie REST查询过滤
【发布时间】:2017-07-11 04:11:49
【问题描述】:

我希望对 django 网络应用程序进行更改,该应用程序通过美味派提供 REST 接口。该应用程序位于:
https://github.com/OWASP/django-DefectDojo/

在应用内,用户拥有他们有权查看的产品和属于产品端点 .

模型定义在:
https://github.com/OWASP/django-DefectDojo/blob/master/dojo/models.py#L177 https://github.com/OWASP/django-DefectDojo/blob/master/dojo/models.py#L417

我已将 EndpointResource 添加到dojo/api.py

class EndpointResource(BaseModelResource):
    class Meta:
        queryset = Endpoint.objects.all()
        resource_name = 'endpoints'
        fields = ['product', 'protocol', 'host', 'path', 'query', 'fragment']

        list_allowed_methods = ['get']
        detail_allowed_methods = ['get']
        include_resource_uri = True
        filtering = {
            'product': ALL,
            'protocol': ALL,
            'host': ALL,
        }
        authorization = DjangoAuthorization()
        authentication = DojoApiKeyAuthentication()
        serializer = Serializer(formats=['json'])

类产品包含:
authorized_users = models.ManyToManyField(User, blank=True)
类端点包含:
product = models.ForeignKey(Product, null=True, blank=True, )

目前,用户可以通过/api/v1/endpoints/ 进行身份验证,他们将看到所有端点。

curl -v --header 'Authorization: ApiKey sue:5b632d76ef1a38b8375383e3498d063515b356d4' http://example.com/api/v1/endpoints/

但是,期望的行为是用户应该只能访问他们获得授权的产品,以及这些产品的相关实体。

在 python 会话中我可以做到:

>>> from dojo.models import User, Product, Endpoint
>>> User.objects.get(username='sue').product_set.all().get().endpoint_set.all()
[<Endpoint: goliath.sue.local>, <Endpoint: goliath.suelimited.co>, <Endpoint: 192.168.10.11>]

这些与“sue”关联的对象是我希望 API 返回的对象。
用美味的派来解决这个问题的最佳方法是什么?
非常感谢任何帮助,如果我需要发布更多信息,请告诉我。

【问题讨论】:

    标签: python django rest tastypie


    【解决方案1】:

    使用链接中的代码 https://github.com/OWASP/django-DefectDojo/blob/master/dojo/finding/views.py#L68 作为指导,在 EndpointResource 类中添加了以下方法:

    def get_object_list(self, request):
        return super(EndpointResource, self).get_object_list(request).filter(product__authorized_users__in=[request.user])
    

    它的表现与我描述的一样,但有兴趣获得反馈,看看它是否正确。

    【讨论】:

    • 这也很好用。根据here 的说明,所有进来的请求都必须通过get_object_list,不要与get_list 混淆,后者是列出对象的API 调用。如果您想跨多个资源重用该类,Authorization 方法(我的意思是继承 DjangoAuthorization)效果更好。
    • 另外,我想部分原因也是设计选择。使用Authorization 方法允许您根据请求类型(例如列表与详细信息)采取不同的行动。使用过滤方法意味着客户端将获得 404 尝试访问他们没有权限的端点,而不是在 read_detail 方法中引发 Unauthorized。取决于你喜欢哪个。 Authorization 类的设计目的是确定谁可以访问什么,所以这是我的建议。万事如意!
    • 我倾向于通用的 404,这样资源就不能被枚举用于顽皮的目的。再次感谢!
    【解决方案2】:

    最简单的方法可能是继承DjangoAuthorization。在文档here 中查看更多信息。

    from tastypie.authorization import DjangoAuthorization
    
    from tastypie.exceptions import Unauthorized
    
    
    class UserEndpointAuthorization(DjangoAuthorization):
    
        def read_list(self, object_list, bundle):
            # Do your filter here against the queryset to limit it
            # to only the endpoints they can see.
            return object_list.filter(....)
    

    【讨论】:

    • 谢谢 jaywhy13,当前的 DjangoAuthorization 工作正常,所以宁愿离开。我在下面添加了一个可行的答案,但有兴趣看看它是否正确。
    猜你喜欢
    • 2013-05-12
    • 2015-11-10
    • 2021-03-17
    • 2023-03-17
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    相关资源
    最近更新 更多