Django中如何要求已登录用户确认密码后才可访问特定页面
Django 仪表盘每次访问密码验证实现方案
核心逻辑是在现有登录验证的基础上,新增一层仪表盘专属的校验逻辑:每次访问仪表盘路由时,检查Session中是否存在自定义的「仪表盘已验证」标记,无标记则跳转至密码验证页面,校验当前登录用户的登录密码,验证通过后再写入标记放行。
步骤1:新建密码校验表单
仅需要密码字段,校验逻辑直接调用Django自带的用户密码校验方法即可:
# your_app/forms.py from django import forms class DashboardPwdVerifyForm(forms.Form): password = forms.CharField(widget=forms.PasswordInput, label="请输入登录密码") def __init__(self, *args, **kwargs): self.current_user = kwargs.pop('user', None) super().__init__(*args, **kwargs) def clean_password(self): input_pwd = self.cleaned_data.get('password') if not self.current_user.check_password(input_pwd): raise forms.ValidationError("密码错误,请重新输入") return input_pwd
步骤2:实现密码验证视图
# your_app/views.py from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from .forms import DashboardPwdVerifyForm @login_required def dashboard_verify(request): # 已经验证过直接跳转仪表盘 if request.session.get('dashboard_verified', False): return redirect('dashboard') if request.method == 'POST': form = DashboardPwdVerifyForm(request.POST, user=request.user) if form.is_valid(): # 验证通过写入Session标记,可自定义有效期,示例设为10分钟(600秒) request.session['dashboard_verified'] = True request.session.set_expiry(600) # 跳转至用户原本要访问的仪表盘地址 next_url = request.GET.get('next', 'dashboard') return redirect(next_url) else: form = DashboardPwdVerifyForm(user=request.user) return render(request, 'dashboard_verify.html', {'form': form})
步骤3:编写验证页模板
<!-- templates/dashboard_verify.html --> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">确认验证</button> {% for error in form.errors.values %} <p style="color: #ff4444;">{{ error.0 }}</p> {% endfor %} </form>
步骤4:给仪表盘加校验逻辑
两种方案按需选择即可:
方案A:自定义装饰器(适合少量仪表盘视图)
先写装饰器:
# your_app/decorators.py from django.shortcuts import redirect def need_dashboard_verify(view_func): def wrapper(request, *args, **kwargs): if not request.session.get('dashboard_verified', False): return redirect(f'/dashboard/verify/?next={request.path}') return view_func(request, *args, **kwargs) return wrapper
给仪表盘视图加装饰器:
@login_required @need_dashboard_verify def dashboard(request): # 你的仪表盘业务逻辑 return render(request, 'dashboard.html')
方案B:中间件(适合所有/dashboard开头的路由都要校验的场景)
编写中间件:
# your_app/middleware.py from django.shortcuts import redirect class DashboardVerifyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): path = request.path # 排除验证页本身,避免死循环 if path.startswith('/dashboard/') and path != '/dashboard/verify/': if request.user.is_authenticated and not request.session.get('dashboard_verified', False): return redirect(f'/dashboard/verify/?next={path}') return self.get_response(request)
在settings.py中注册中间件,注意要放在SessionMiddleware和AuthenticationMiddleware之后:
MIDDLEWARE = [ # 其他默认中间件 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', # 新增你的中间件 'your_app.middleware.DashboardVerifyMiddleware', ]
步骤5:配置路由
# your_app/urls.py from django.urls import path from . import views urlpatterns = [ # 其他路由 path('dashboard/verify/', views.dashboard_verify, name='dashboard_verify'), path('dashboard/', views.dashboard, name='dashboard'), ]
注意:如果需要严格实现「每次访问都必须输密码验证」,直接去掉Session中dashboard_verified标记的写入逻辑即可,不过该场景用户体验较差,一般建议设置5-15分钟的验证有效期平衡安全性和使用体验。
内容的提问来源于stack exchange,提问作者R-Cilia
相关产品推荐
相关产品推荐

