我正在为移动应用开发Django Rest Framework后端。 API是私有的,只能在内部使用。
可浏览的API便于帮助开发人员处理项目,但我希望阻止任何未设置为项目管理员的人使用可浏览界面。
我意识到可浏览的管理员不会授予用户不会拥有的任何权限,但它确实有一些安全灰色区域(例如,对于具有外键关系的模型,HTML选择器字段会填充所有DB中可能的相关对象,除非您明确指示不要)。
由于此应用处理敏感的用户数据,我更愿意向公众公开可能的最小表面区域,以降低我自己潜在错误疏忽的风险。
有没有办法为非管理员用户禁用可浏览的API而不为每个人禁用它?我已经做了大量的Google搜索并查看了SO并且没有找到答案。这个问题很接近How to disable admin-style browsable interface of django-rest-framework?但不一样,因为这些说明会禁用每个人的界面。
答案 0 :(得分:1)
“ DEFAULT_PERMISSION_CLASSES”设置是否不够?这为所有视图DRF docs on default permission classes
设置了默认限制在settings.py
中:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser',
]
}
它们将“到达”可浏览的界面,但是如果未经授权,所有类型的请求都将被拒绝。
如果非管理员用户出于某种原因需要达到各种端点,则可以逐个视图地放宽限制。
答案 1 :(得分:1)
假设您使用的是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
答案 2 :(得分:0)
在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