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

自定义AuthBackend后,无法使用Django的is_authenticated及@login_required问题求助

解决Django迁移PHP应用时自定义User模型无法使用@login_required的问题

问题描述

我有PHP开发背景,刚接触Django,正在把一款Web应用从PHP框架迁移到Django,必须保留原有数据库结构。我的User表结构和Django自带的auth.User模型不符,已经通过自定义AuthBackend完成了认证功能,但登录后使用@login_required装饰器时会报错:'User' object has no attribute 'is_authenticated'。我不想让User模型继承auth.AbstractUser或auth.AbstractBaseUser,因为要保留原表结构,该如何解决?

问题补充:自定义User模型代码

class User(models.Model):
    employee = models.ForeignKey(Employee, models.DO_NOTHING)
    user_role = models.ForeignKey(UserRole, models.DO_NOTHING, blank=True, null=True)
    username = models.CharField(max_length=50, blank=False, null=False)
    password = models.CharField(max_length=50, blank=True, null=True)
    created_on = models.DateTimeField()
    last_updated_on = models.DateTimeField(blank=True, null=True)
    last_password_change = models.DateTimeField(blank=True, null=True)
    status = models.IntegerField(db_comment='0-Deleted, 1-Active, 2-New')
    last_login  = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'

解决方案

1. 给自定义User模型添加is_authenticated属性

Django的@login_required装饰器依赖用户模型的is_authenticated属性(Django 1.10+已改为属性而非方法),直接在你的User模型中添加这个属性即可:

class User(models.Model):
    # 原有字段保持不变...
    employee = models.ForeignKey(Employee, models.DO_NOTHING)
    user_role = models.ForeignKey(UserRole, models.DO_NOTHING, blank=True, null=True)
    username = models.CharField(max_length=50, blank=False, null=False)
    password = models.CharField(max_length=50, blank=True, null=True)
    created_on = models.DateTimeField()
    last_updated_on = models.DateTimeField(blank=True, null=True)
    last_password_change = models.DateTimeField(blank=True, null=True)
    status = models.IntegerField(db_comment='0-Deleted, 1-Active, 2-New')
    last_login  = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'

    # 添加is_authenticated属性,根据业务逻辑判断用户是否已认证
    @property
    def is_authenticated(self):
        # 这里以status=1(Active)作为已认证/活跃的判断条件
        return self.status == 1

2. 补充兼容Django认证系统的必要属性(可选但推荐)

为了避免后续出现其他兼容性问题,建议添加Django认证系统预期的其他核心属性:

# 在User模型中继续添加以下属性
@property
def is_active(self):
    # 与is_authenticated逻辑一致,判断用户是否处于活跃状态
    return self.status == 1

@property
def is_anonymous(self):
    # 自定义用户实例肯定不是匿名用户,固定返回False
    return False

def get_username(self):
    # 返回模型中的username字段,匹配Django的预期接口
    return self.username

3. 确保自定义AuthBackend返回正确的User实例

检查你的自定义认证后端,确保authenticate和get_user方法都返回这个自定义的User模型实例:

from django.contrib.auth.backends import BaseBackend
from .models import User

class CustomAuthBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(username=username)
            # 注意:如果原PHP系统的密码是哈希存储,这里要替换成对应的哈希验证逻辑
            if user.password == password and user.status == 1:
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

同时在settings.py中配置这个认证后端:

AUTHENTICATION_BACKENDS = [
    'your_app_name.backends.CustomAuthBackend',  # 替换成你的实际路径
]

4. 验证功能

现在重新启动服务,使用@login_required装饰器的视图应该可以正常工作了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:07:04