我在基于django-rest-framework
的应用程序中进行(或多或少)自定义身份验证,我只需要调用另一个微服务来询问令牌是否有效以及与哪个用户名/用户ID相关联用它。 (我没有为用户提供本地表格。)
找不到开箱即用的解决方案,我正在覆盖dispatch
方法(我正在使用基于APIView
的视图),在那里我向远程服务发出请求,如果响应不是200,我想返回403错误。
这是我的代码:
def dispatch(self, request, *args, **kwargs):
try:
user_info = user_from_token_in_request(request)
return super().dispatch(*args, **kwargs)
except:
return Response(
"No Auth Token provided or bad Auth Token"
status.HTTP_403_FORBIDDEN,
)
但是,当我传递无效令牌时,我收到此错误:AssertionError: .accepted_renderer not set on Response
,因为在处理dispatch
方法时未初始化响应上下文。
有没有更合适的方法呢?
答案 0 :(得分:4)
而不是返回Response
尝试引发DRF
提供的异常之一,而异常处理程序将自动处理其余的异常。
from rest_framework.exceptions import PermissionDenied
def dispatch(self, request, *args, **kwargs):
try:
# ...
except:
raise PermissionDenied("NO Auth Token provided")
话虽如此,建议不要在您的视图中编写您的身份验证代码。您应该在自定义身份验证/权限类中完成此操作。
from rest_framework.authentication import BaseAuthentication
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
try:
user_info = user_from_token_in_request(request)
except:
raise AuthenticationFailed('No auth token provided')
class MyApiView(APIView):
authentication_classes = [MyAuthentication]
另外请确保您已在休息框架设置中定义了EXCEPTION_HANDLER
。
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}
答案 1 :(得分:2)
要回答原始问题,在handle_exception
内部调用dispatch
,因此,如果您要覆盖dispatch
,将不会自动为您调用。但是您可以直接调用它:
from rest_framework.exceptions import PermissionDenied
class SometimesErrorMixin:
should_error = None
def dispatch(self, request, *args, **kwargs):
if not self.should_error:
return super().dispatch(request, *args, **kwargs)
# Lifted from DRF
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
response = self.handle_exception(PermissionDenied())
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
将此Mixin放在ViewSet的最左侧以使用该行为。显然,您可以使用适当的逻辑替换should_error
。