将未经身份验证的用户重定向到登录表单。

huangapple go评论125阅读模式
英文:

DRF: Redirect unauthenticated users to login form

问题

有没有一种方法可以将没有通过rest_framework.permissions.IsAuthenticated权限的用户重定向到登录页面?

我可以通过重写我的ApiView的dispatch方法并添加额外的NotAuthenticated异常捕获来实现这一点,但是否有更软性的方法来做到这一点?

  1. class IndexView(APIView):
  2. permission_classes = [
  3. IsAuthenticated,
  4. ]
  5. def get(self, request, format=None):
  6. ...
  7. def dispatch(self, request, *args, **kwargs):
  8. self.args = args
  9. self.kwargs = kwargs
  10. request = self.initialize_request(request, *args, **kwargs)
  11. self.request = request
  12. self.headers = self.default_response_headers # deprecate?
  13. try:
  14. self.initial(request, *args, **kwargs)
  15. # Get the appropriate handler method
  16. if request.method.lower() in self.http_method_names:
  17. handler = getattr(self, request.method.lower(),
  18. self.http_method_not_allowed)
  19. else:
  20. handler = self.http_method_not_allowed
  21. response = handler(request, *args, **kwargs)
  22. except NotAuthenticated: # <---- 由我添加
  23. return redirect("/login")
  24. except Exception as exc:
  25. response = self.handle_exception(exc)
  26. self.response = self.finalize_response(request, response, *args, **kwargs)
  27. 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?

  1. class IndexView(APIView):
  2. permission_classes = [
  3. IsAuthenticated,
  4. ]
  5. def get(self, request, format=None):
  6. ...
  7. def dispatch(self, request, *args, **kwargs):
  8. self.args = args
  9. self.kwargs = kwargs
  10. request = self.initialize_request(request, *args, **kwargs)
  11. self.request = request
  12. self.headers = self.default_response_headers # deprecate?
  13. try:
  14. self.initial(request, *args, **kwargs)
  15. # Get the appropriate handler method
  16. if request.method.lower() in self.http_method_names:
  17. handler = getattr(self, request.method.lower(),
  18. self.http_method_not_allowed)
  19. else:
  20. handler = self.http_method_not_allowed
  21. response = handler(request, *args, **kwargs)
  22. except NotAuthenticated: &quot;&lt;---- added by me&quot;
  23. return redirect(&quot;/login&quot;)
  24. except Exception as exc:
  25. response = self.handle_exception(exc)
  26. self.response = self.finalize_response(request, response, *args, **kwargs)
  27. return self.response

答案1

得分: 1

以下是翻译好的部分:

你可以通过重写rest框架的异常处理程序来按如下方式执行:

在任何应用程序中创建一个名为handler.py的新文件,并添加如下内容:

  1. from rest_framework.exceptions import PermissionDenied
  2. from rest_framework.views import exception_handler
  3. from django.shortcuts import redirect
  4. def redirect_to_log(exec, data):
  5. if isinstance(exec, PermissionDenied):
  6. return redirect('login')
  7. return exception_handler(exec, data)

然后,在你的settings.py文件中进行以下更改:

  1. REST_FRAMEWORK = {
  2. 'EXCEPTION_HANDLER': 'app.handler.redirect_to_log'
  3. }

现在,每当权限检查失败时,用户将被重定向到登录页面。

注意: 这适用于任何失败的异常。要有更深入的控制,你可以重写APIView或Viewsets中的handle_exception方法。

编辑:

要根据每个视图/视图集进行设置,你可以使用以下方法:

在你的serializers.py文件中创建一个自定义的PermissionDenied包装器,如下所示:

  1. from rest_framework.exceptions import PermissionDenied
  2. class RedirectToLoginException(PermissionDenied):
  3. pass
  4. class CheckUserPermission(BasePermission):
  5. def has_permission(self, request, view):
  6. # 检查用户是否已经认证的逻辑
  7. if not_allowed:
  8. raise RedirectToLoginException

现在,在你的APIView中,你可以按如下方式操作:

  1. from your_app.permissions import RedirectToLoginException, CheckUserPermission
  2. class IndexView(APIView):
  3. permission_classes = [CheckUserPermission]
  4. def handle_exception(self, exc):
  5. if isinstance(exc, RedirectToLoginException):
  6. return redirect('login')
  7. else:
  8. 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:

  1. from rest_framework.exceptions import PermissionDenied
  2. from rest_framework.views import exception_handler
  3. from django.shortcuts import redirect
  4. def redirect_to_log(exec, data):
  5. if isinstance(exec, PermissionDenied):
  6. return redirect(&#39;login&#39;)
  7. return exception_handler(exec, data)

Then, make this change in your settings.py file:

  1. REST_FRAMEWORK = {
  2. &#39;EXCEPTION_HANDLER&#39;: &#39;app.handler.redirect_to_log&#39;
  3. }

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

  1. class RedirectToLoginException(PermissionDenied):
  2. pass
  3. class CheckUserPermission(BasePermission):
  4. def has_permission(self, request, view):
  5. # your logic for checking if user is authenticated or not
  6. if not_allowed:
  7. raise RedirectToLoginException

Now, in your APIView you can do as follows:

  1. from your_app.permissions import RedirectToLoginException, CheckUserPermission
  2. class IndexView(APIView):
  3. permission_classes = [CheckUserPermission]
  4. def handle_exception(self, exc):
  5. if isinstance(exc, RedirectToLoginException):
  6. return redirect(&#39;login&#39;)
  7. else:
  8. super().handle_exception(exc)

By this method, only when permission checks for CheckUserPermission fails, you will be redirected to the login page.

huangapple
  • 本文由 发表于 2023年8月10日 18:27:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76874867.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定