英文:
DRF: Redirect unauthenticated users to login form
问题
有没有一种方法可以将没有通过rest_framework.permissions.IsAuthenticated
权限的用户重定向到登录页面?
我可以通过重写我的ApiView的dispatch方法并添加额外的NotAuthenticated异常捕获来实现这一点,但是否有更软性的方法来做到这一点?
class IndexView(APIView):
permission_classes = [
IsAuthenticated,
]
def get(self, request, format=None):
...
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except NotAuthenticated: # <---- 由我添加
return redirect("/login")
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
英文:
Is there a way to redirect users who didn't pass through rest_framework.permissions.IsAuthenticated
permission to login page?
I can achieve it by rewriting dispatch method of my ApiView and adding extra
NotAuthenticated exception catcher, but is there a softer way to do this?
class IndexView(APIView):
permission_classes = [
IsAuthenticated,
]
def get(self, request, format=None):
...
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except NotAuthenticated: "<---- added by me"
return redirect("/login")
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
答案1
得分: 1
以下是翻译好的部分:
你可以通过重写rest框架的异常处理程序来按如下方式执行:
在任何应用程序中创建一个名为handler.py
的新文件,并添加如下内容:
from rest_framework.exceptions import PermissionDenied
from rest_framework.views import exception_handler
from django.shortcuts import redirect
def redirect_to_log(exec, data):
if isinstance(exec, PermissionDenied):
return redirect('login')
return exception_handler(exec, data)
然后,在你的settings.py
文件中进行以下更改:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app.handler.redirect_to_log'
}
现在,每当权限检查失败时,用户将被重定向到登录页面。
注意: 这适用于任何失败的异常。要有更深入的控制,你可以重写APIView或Viewsets中的handle_exception方法。
编辑:
要根据每个视图/视图集进行设置,你可以使用以下方法:
在你的serializers.py
文件中创建一个自定义的PermissionDenied
包装器,如下所示:
from rest_framework.exceptions import PermissionDenied
class RedirectToLoginException(PermissionDenied):
pass
class CheckUserPermission(BasePermission):
def has_permission(self, request, view):
# 检查用户是否已经认证的逻辑
if not_allowed:
raise RedirectToLoginException
现在,在你的APIView中,你可以按如下方式操作:
from your_app.permissions import RedirectToLoginException, CheckUserPermission
class IndexView(APIView):
permission_classes = [CheckUserPermission]
def handle_exception(self, exc):
if isinstance(exc, RedirectToLoginException):
return redirect('login')
else:
super().handle_exception(exc)
通过这种方法,只有在CheckUserPermission权限检查失败时,才会重定向到登录页面。
英文:
You can do it as follows by overriding the exception handler of rest framework:
create a new file in any app with the name handler.py
and add as follows:
from rest_framework.exceptions import PermissionDenied
from rest_framework.views import exception_handler
from django.shortcuts import redirect
def redirect_to_log(exec, data):
if isinstance(exec, PermissionDenied):
return redirect('login')
return exception_handler(exec, data)
Then, make this change in your settings.py
file:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app.handler.redirect_to_log'
}
Now, whenever the permission check fails, the user will be redirected to the login page.
Note: This applies to any of the exception where ever it fails. To have a more ingrain control, you can override the handle_exception in APIView or Viewsets
EDIT:
To do it per view/viewset basis you can user the following approach
In your serializers.py
file create a custom PermissionDenied
wrapper as follows:
from rest_framework.exceptions import PermissionDenied
class RedirectToLoginException(PermissionDenied):
pass
class CheckUserPermission(BasePermission):
def has_permission(self, request, view):
# your logic for checking if user is authenticated or not
if not_allowed:
raise RedirectToLoginException
Now, in your APIView you can do as follows:
from your_app.permissions import RedirectToLoginException, CheckUserPermission
class IndexView(APIView):
permission_classes = [CheckUserPermission]
def handle_exception(self, exc):
if isinstance(exc, RedirectToLoginException):
return redirect('login')
else:
super().handle_exception(exc)
By this method, only when permission checks for CheckUserPermission fails, you will be redirected to the login page.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论