我正在尝试使用Django REST framework向使用Django OAuth2 toolkit的现有代码库添加API。现有视图利用OAuth2工具包的后端修改Django的login_required
装饰器的行为以便它使用OAuth2身份验证的事实。基于函数的视图类似于教程示例中的视图:
from django.contrib.auth.decorators import login_required
from django.http.response import HttpResponse
@login_required()
def secret_page(request, *args, **kwargs):
return HttpResponse('Secret contents!', status=200)
我正在尝试将https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html上给出的示例调整到我的情况,但我发现它不是完全对应,因为该示例使用DRF的ModelViewSet
类,而我当前的视图使用一个(集成度较低)通用的基于类的视图:
from rest_framework import generics
from ..models import Session
from ..serializers import SessionSerializer
class SessionDetail(generics.UpdateAPIView):
queryset = Session.objects.all()
serializer_class = SessionSerializer
我在IsAuthenticated
中将默认权限类设置为settings.py
:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
这应该允许使用PATCH请求更新Session
对象,但它似乎返回403 Forbidden
响应用例,类似于用login_required
修饰的当前视图的用例
如何更新SessionDetail
视图,使其与使用login_required
修饰的功能视图的行为相同?我怀疑我需要使用TokenHasReadWriteScope权限类,因为这似乎是唯一一个required_scopes
是可选的。 (用login_required
修饰的视图也不提供required_scopes
。
会是这样的吗?
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from oauth2_provider.contrib.rest_framework import OAuth2Authentication, TokenHasReadWriteScope
from ..models import Session
from ..serializers import SessionSerializer
class SessionDetail(generics.UpdateAPIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasReadWriteScope]
queryset = Session.objects.all()
serializer_class = SessionSerializer
另外,我是否需要使用REST_FRAMEWORK
更新我的DEFAULT_AUTHENTICATION_CLASSES
设置:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
)
}
现在,如果我运行服务器并尝试使用可浏览的API发出补丁请求,则会出现401 Unauthorized
错误:
此外,如果我Log in
使用我刚刚使用python manage.py createsuperuser
创建的用户名和密码,它会直接返回此401
页面,而不是使用表单进行PATCH请求的页面正如我所料。
有关如何解决此问题的任何想法?