DJANGO 中间件的白名单配置

发布于:2025-03-22 ⋅ 阅读:(51) ⋅ 点赞:(0)

在处理白名单内的多个 Apps 的 URL 链接时,可以采用以下几种方法来简化白名单的配置:

1. 使用 reverse 动态获取 URL

如果你在 urls.py 中为每个 App 的 URL 定义了名称(name 参数),可以使用 reverse 函数动态获取这些 URL,而不是硬编码路径。这样可以避免手动维护大量的路径字符串。

Python复制

from django.urls import reverse

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

    def __call__(self, request):
        # 动态获取白名单中的 URL
        white_list = [
            reverse('login'),  # 登录页面
            reverse('logout'),  # 注销页面
            reverse('admin:index'),  # Django 管理页面
            # 其他 App 的 URL 名称
            reverse('app1:view1'),
            reverse('app2:view2'),
        ]

        # 如果用户未登录且请求的路径不在白名单中,重定向到登录页面
        if not request.user.is_authenticated and request.path not in white_list:
            return redirect('login')

        response = self.get_response(request)
        return response

2. 使用 URL 前缀匹配

如果你的多个 App 的 URL 都有共同的前缀,可以通过前缀匹配来简化白名单的配置。例如,所有以 /public/ 开头的 URL 都不需要登录。

Python复制

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

    def __call__(self, request):
        # 白名单前缀
        white_list_prefixes = [
            '/login/',
            '/logout/',
            '/admin/',
            '/public/',  # 所有以 /public/ 开头的 URL
        ]

        # 检查请求路径是否以白名单前缀开头
        if any(request.path.startswith(prefix) for prefix in white_list_prefixes):
            # 如果路径以白名单前缀开头,直接放行
            pass
        elif not request.user.is_authenticated:
            # 如果用户未登录且路径不在白名单中,重定向到登录页面
            return redirect('login')

        response = self.get_response(request)
        return response

3. 使用正则表达式匹配

对于更复杂的匹配需求,可以使用正则表达式来匹配多个路径模式。

Python复制

import re

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

    def __call__(self, request):
        # 使用正则表达式定义白名单
        white_list_patterns = [
            re.compile(r'^/login/$'),  # 匹配 /login/
            re.compile(r'^/logout/$'),  # 匹配 /logout/
            re.compile(r'^/admin/'),  # 匹配 /admin/ 开头的路径
            re.compile(r'^/public/'),  # 匹配 /public/ 开头的路径
        ]

        # 检查请求路径是否匹配白名单中的正则表达式
        if any(pattern.match(request.path) for pattern in white_list_patterns):
            # 如果路径匹配白名单中的正则表达式,直接放行
            pass
        elif not request.user.is_authenticated:
            # 如果用户未登录且路径不在白名单中,重定向到登录页面
            return redirect('login')

        response = self.get_response(request)
        return response

4. 集中管理白名单

如果你的项目中有多个中间件都需要使用白名单,可以将白名单的配置提取到一个单独的文件中,方便集中管理和维护。

Python复制

# myproject/settings.py
# 定义白名单配置
WHITE_LIST_URLS = [
    'login',
    'logout',
    'admin:index',
    'app1:view1',
    'app2:view2',
]

# myapp/middleware.py
from django.urls import reverse
from django.conf import settings

class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 动态生成白名单 URL 列表
        self.white_list = [reverse(url_name) for url_name in settings.WHITE_LIST_URLS]

    def __call__(self, request):
        # 如果用户未登录且请求的路径不在白名单中,重定向到登录页面
        if not request.user.is_authenticated and request.path not in self.white_list:
            return redirect('login')

        response = self.get_response(request)
        return response

通过以上方法,可以更灵活、更简洁地管理白名单中的多个 Apps 的 URL 链接,减少硬编码和重复配置。