在Django项目中使用中间件类进行用户身份验证

2024-05-16 22:51:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我公司的一个项目在Django,我被分配到一项任务“向顶级路由器添加身份验证”,因此我们不会忘记向每个视图添加身份验证代码,例如:

if not request.user.is_authenticated:
    return HttpResponseRedirect('/admin/login/?next=/admin/some-page/')

在做了一些研究之后,我发现这可以通过编写自己的中间件来实现。在做作业之前,我对这个概念一点也不熟悉。因此,现在我正在尝试编写一个LoginRequiredMiddleware类,该类截取每个请求,并在未经身份验证的情况下将用户发送到登录页面,在身份验证后,发送到用户试图访问的原始页面

这是我目前掌握的代码。 middleware.py

from django.conf import settings
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import is_safe_url
import re


EXEMPT_URLS = [re.compile(settings.LOGIN_REDIRECT_URL.lstrip('/'))] # '/admin'


class LoginRequiredMiddleware(MiddlewareMixin):

    def process_request(self, request):
        assert hasattr(request, 'user'), "The Login Required Middleware"
        if not request.user.is_authenticated:
            path = request.path_info.lstrip('/')
            
            if not any(m.match(path) for m in EXEMPT_URLS):
                redirect_to = settings.LOGIN_REDIRECT_URL

                if len(path) > 0 and is_safe_url(
                      url=request.path_info, allowed_hosts=request.get_host()):
                    redirect_to = f"{settings.LOGIN_REDIRECT_URL}/login?next={request.path_info}"

                return HttpResponseRedirect(redirect_to)

我已经在settings.pyMIDDLEWARE列表中注册了中间件,并且包括了SessionMiddlewareAuthenticationMiddleware,但我还没有设法让它工作。例如,我可以在匿名模式下访问需要身份验证的页面,而无需登录

我想知道我做错了什么,或者我应该走哪条更好的路


Tags: pathdjangofromimport身份验证urlifsettings
1条回答
网友
1楼 · 发布于 2024-05-16 22:51:30
import re

from django.conf import settings
from django.shortcuts import redirect
from django.contrib.auth import logout
from django.utils.deprecation import MiddlewareMixin


EXEMPT_URLS = [re.compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
    EXEMPT_URLS += [re.compile(url) for url in settings.LOGIN_EXEMPT_URLS]
# Other login exempt urls can be added in settings with 'LOGIN_EXEMPT_URLS'


class LoginRequiredMiddleware(MiddlewareMixin):
    def __init__(self, get_response):
        self.get_response = get_response

    def process_request(self, request):
        assert hasattr(request, 'user')

        path = request.path_info.lstrip('/')

        for endpoint in ["api/", "settings", "mfa", "reset"]:
            if path.startswith(endpoint):
                return self.get_response(request)

        url_is_exempt = any(url.match(path) for url in EXEMPT_URLS)

        if path == settings.LOGOUT_URL.lstrip('/'):
            logout(request)

        if request.user.is_authenticated and url_is_exempt:
            # If the user is authenticated and the URL is in the exempt list
            # redirect to the login page
            return redirect(settings.LOGIN_REDIRECT_URL)

        elif request.user.is_authenticated or url_is_exempt:
            # Do nothing if the user is authenticated and the URL is not in the
            # exempt list
            return None

        else:
            # Trying to access any page as a non authenticated user
            return redirect(f"{settings.LOGIN_URL}?next=/{path}")

相关问题 更多 >