You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义认证异常:Agent登录未校验凭证的问题排查与修复

Django Agent登录认证失效问题排查与修复

问题原因

  • 认证参数未传递:agent_login视图调用AgentBackend.authenticate(request)时,未传入获取到的username和password,导致后端authenticate方法直接返回None,但视图仍无条件跳转至仪表盘页面。
  • 表单字段定义错误:AgentSignInForm中password字段直接赋值为PasswordInput(),不符合Django表单字段定义规范,无法正确处理密码输入。
  • 无认证失败处理逻辑:视图未对认证结果做判断,无论凭证正确与否都直接渲染仪表盘页面。
  • 未维持登录状态:认证成功后未将Agent对象存入session,后续访问仪表盘视图时无法验证身份,也无法实现持久化登录。

修复方案

1. 修正forms.py中的AgentSignInForm

from django import forms
from django.contrib.auth.forms import AuthenticationForm

class AgentSignInForm(AuthenticationForm):
    username = forms.CharField(max_length=100)
    # 修正password字段定义,通过widget指定密码输入类型
    password = forms.CharField(widget=forms.PasswordInput())
    
    def clean(self):
        cleaned_data = super().clean()
        username = cleaned_data.get('username')
        password = cleaned_data.get('password')
        if not username or not password:
            raise forms.ValidationError("用户名和密码不能为空")
        return cleaned_data

2. 修正views.py中的agent_login视图

from django.shortcuts import render, redirect
from django.contrib.auth import login
from .forms import AgentSignInForm
from .backends import AgentBackend

def agent_login(request):
    if request.method == 'POST':
        form = AgentSignInForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            # 传递username和password给authenticate方法
            agent = AgentBackend().authenticate(request, username=username, password=password)
            if agent:
                # 用Django内置login方法将agent存入session,维持登录状态
                login(request, agent, backend='users.backends.AgentBackend')
                # 重定向到仪表盘DetailView对应的URL
                return redirect('agent_dashboard', slug=agent.slug)
            else:
                # 认证失败时添加错误提示
                form.add_error(None, "用户名或密码错误")
        return render(request, 'users/agent_login.html', {'form': form})
    else:
        form = AgentSignInForm()
    return render(request, 'users/agent_login.html', {'form': form})

3. 完善backends.py中的get_user方法(兼容Django认证规范)

from .models import Agent
from contextlib import suppress
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import check_password

class AgentBackend(BaseBackend):
    def authenticate(request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return

        with suppress(Agent.DoesNotExist):  
            agent = Agent.objects.get(name=username)
            if check_password(password, agent.password):
                return agent
        return None

    def get_user(self, user_id):
        # 兼容id和slug两种查询方式,确保登录状态能正确维持
        with suppress(Agent.DoesNotExist):
            return Agent.objects.get(id=user_id)
        with suppress(Agent.DoesNotExist):
            return Agent.objects.get(slug=user_id)
        return None

4. 保护AgentDashboard视图(防止未登录访问)

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DetailView
from django.shortcuts import redirect
from .models import Agent, Property

class AgentDashboard(LoginRequiredMixin, DetailView):
    model = Agent
    template_name = 'users/agent_dashboard.html'
    slug_field = 'slug'
    # 指定未登录时的跳转地址
    login_url = '/agent/login/'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        agent = self.get_object()
        # 防止越权访问:确保当前登录的agent是页面所属agent
        if self.request.user != agent:
            return redirect('home')
        properties = Property.objects.filter(agent=agent)
        context['properties'] = properties
        return context

5. 修正models.py中的依赖缺失

from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password  # 导入缺失的make_password

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phonenumber = models.IntegerField()

    def __str__(self):
        return f'{self.user.username} Profile'

class Agent(models.Model):
    name = models.CharField(max_length=100)
    password = models.CharField(max_length=200)
    image = models.ImageField(upload_to = 'Images/')
    bio = models.TextField()
    instagram = models.URLField(max_length=100)
    twitter = models.URLField(max_length=100)
    facebook = models.URLField(max_length=100)
    linkedin = models.URLField(max_length=100)
    is_featured = models.BooleanField(default = False)
    slug = models.SlugField(default='')

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
        self.save()  

    def __str__(self):
        return f'{self.name} Agent Profile'

关键说明

  • 使用Django内置login方法维持Agent登录状态,确保后续请求能识别已登录用户。
  • 添加表单验证和错误提示,提升用户体验。
  • 用LoginRequiredMixin保护仪表盘视图,拦截未登录访问。
  • 修正字段定义和依赖缺失,保证代码逻辑完整性。

内容的提问来源于stack exchange,提问作者sasuke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:00:43