如何将 Django Rest Framework 可浏览 API 接口限制为管理员用户
Posted
技术标签:
【中文标题】如何将 Django Rest Framework 可浏览 API 接口限制为管理员用户【英文标题】:How to restrict Django Rest Framework browsable API interface to admin users 【发布时间】:2015-10-09 00:39:44 【问题描述】:我正在为移动应用开发 Django Rest Framework 后端。 API 是私有的,只能在内部使用。
可浏览的 API 可以方便地帮助开发人员处理项目,但我想防止任何未设置为项目管理员的人使用可浏览界面。
我意识到可浏览的管理员不会授予用户否则不会拥有的任何权限,但它确实有一些安全灰色区域(例如,对于具有外键关系的模型,html 选择器字段会填充所有数据库中可能的相关对象,除非您明确指示不要这样做)。
由于此应用处理敏感的用户数据,我更愿意向公众公开尽可能小的表面积,以减少我自己的潜在错误疏忽的风险。
有什么方法可以为非管理员用户禁用可浏览的 API,而不为所有人禁用它?我已经进行了大量的谷歌搜索并查看了 SO 并没有找到答案。这个问题很接近How to disable admin-style browsable interface of django-rest-framework?,但不一样,因为这些说明会禁用所有人的界面。
【问题讨论】:
如何将 html 选择器字段添加到可浏览的 API?它只是文本输入的 html 表单。 但是,如果你真的认为你需要执行这个禁用,你很可能必须子类化 BrowsableApiRenderer,找到一个很好的地方来挂钩并检查 request.user 的管理员状态,然后渲染没有。不过,我认为这是一个糟糕的解决方案。 github.com/tomchristie/django-rest-framework/blob/master/… 我强烈建议在生产环境中删除可浏览的 API(仅在DEBUG
为 True
时将其添加为默认渲染器)。另请注意,如果您的下拉列表暴露了太多信息,那么聪明的人(阅读:其他无聊的开发人员)可能也会链接对象并暴露该数据。
@MarkGalloway 如果您将序列化器字段设置为 PrimaryKeyRelated 等,可浏览的 API 将抛出一个 HTML 选择下拉列表,其中包含所有可能的外键(例如,如果您有系统中的所有用户“用户”外键字段)。这让我感到惊讶,并让我担心可浏览 API 中的信息泄露。
这很酷。我总是声明显式相关的序列化程序,所以我想这就是我从未见过它的原因。
【参考方案1】:
“DEFAULT_PERMISSION_CLASSES”设置不够吗?这对所有视图设置了默认限制DRF docs on default permission classes
在settings.py
:
REST_FRAMEWORK =
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser',
]
他们将“到达”可浏览界面,但如果未经授权,所有类型的请求都将被拒绝。
如果出于某种原因,非管理员用户需要访问各种端点,您可以放宽逐个视图的限制。
【讨论】:
这是一个很好的答案。使用 DEBUG=False 这实质上会禁用生产中的可浏览 api。【参考方案2】:假设您使用的是 DRF 的内置视图,我认为您可以直接覆盖 get_renderers()
。
在您的设置文件中:
REST_FRAMEWORK =
# Only enable JSON renderer by default.
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
然后在你的views.py
:
from rest_framework import generics, renderers
class StaffBrowsableMixin(object):
def get_renderers(self):
"""
Add Browsable API renderer if user is staff.
"""
rends = self.renderer_classes
if self.request.user and self.request.user.is_staff:
rends.append(renderers.BrowsableAPIRenderer)
return [renderer() for renderer in rends]
class CustomListApiView(StaffBrowsableMixin, generics.ListAPIView):
"""
List view.
"""
# normal stuff here
【讨论】:
谢谢!帮我解决了我的问题***.com/q/58884611/420953。欢迎您对它作出相同的回答。您将如何对使用 BrowsableAPIRenderer 进行单元测试? 很高兴它帮助了@udo!单元测试不是我的专长.. 最好只问另一个问题:)【参考方案3】:在rest_framework
视图中,我们有一个名为renderes_classes
的属性
通常我们有一个方法get_<something>
,就像我们对queryset
/get_queryset
一样,但在这种情况下我们没有那个,所以我需要实现一个属性。
from tasks.models import Task
from tasks.serializers import TaskSerializer
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.renderers import CoreJSONRenderer
class CustomRendererView:
permission_classes = (IsAuthenticatedOrReadOnly,)
@property
def renderer_classes(self):
renderers = super(ListTask, self).renderer_classes
if not self.request.user.is_staff:
renderers = [CoreJSONRenderer]
return renderers
class ListTask(CustomRendererView, ListAPIView):
queryset = Task.objects.all()
serializer_class = FullTaskSerializer
【讨论】:
以上是关于如何将 Django Rest Framework 可浏览 API 接口限制为管理员用户的主要内容,如果未能解决你的问题,请参考以下文章
如何仅使用 django 作为后端并使用 django-rest-framework 发布
Django - 如何通过 API 端点使用 rest_framework 动态地将多个对象添加到数据库中
如何使用 django-rest-framework 进行社交登录? [关闭]
如何将命名空间 url 添加到 django-rest-framework 路由器视图集