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

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

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: &quot;&lt;----  added by me&quot;
            return redirect(&quot;/login&quot;)
        
        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(&#39;login&#39;)
    return exception_handler(exec, data)

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

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

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(&#39;login&#39;)
        else:
            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:

确定