在Django项目中使用中间件class进行用户认证

Using middleware class for user authentication in Django project

我公司的一个项目是在Django中,我被分配了一个任务给'add authentication to the top-level router'所以我们不要忘记为每个视图添加一个验证码,例如:

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

经过一番研究后,我发现这可以通过编写自己的中间件来实现。在做作业之前,我根本不熟悉这个概念。所以现在我正在尝试编写一个 LoginRequiredMiddleware class 来拦截每个请求,如果未通过身份验证,则将用户发送到登录页面,并在身份验证后发送到用户尝试访问的原始页面。

这是我目前的代码。 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,但我还没有设法让它工作。我可以在隐身模式下访问需要身份验证的页面,例如,无需登录。

我想要一些关于我做错了什么或我应该遵循哪条更好的道路的提示。

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}")