如何基于PostgreSQL自定义表实现Django用户认证后端
自定义Django认证后端实现指南
首先你的Profile模型存在逻辑冲突:它既继承了AbstractBaseUser(自定义用户模型基类),又关联了默认User模型,这会导致认证流程混乱。以下是完整的修正和实现步骤:
1. 修正自定义用户模型
将原Profile调整为标准自定义用户模型,替代默认User:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin class CustomUserManager(BaseUserManager): # 创建普通用户 def create_user(self, user_name, email, password=None, **extra_fields): if not user_name: raise ValueError("必须设置用户名") if not email: raise ValueError("必须设置邮箱") email = self.normalize_email(email) user = self.model(user_name=user_name, email=email, **extra_fields) user.set_password(password) # 自动哈希处理密码 user.save(using=self._db) return user # 创建超级用户 def create_superuser(self, user_name, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) return self.create_user(user_name, email, password, **extra_fields) class CustomUser(AbstractBaseUser, PermissionsMixin): first_name = models.TextField() last_name = models.TextField() user_name = models.TextField(unique=True) email = models.TextField(unique=True) date_created = models.DateTimeField(auto_now_add=True) is_active = models.BooleanField(default=True) # 标记用户是否可用 is_staff = models.BooleanField(default=False) # 标记是否可登录后台 USERNAME_FIELD = 'user_name' # 登录用的唯一标识字段 REQUIRED_FIELDS = ['email'] # 创建超级用户时必填的额外字段 objects = CustomUserManager() # 绑定自定义管理器 def __str__(self): return self.user_name
关键修正说明:
- 移除与默认
User的一对一关联,CustomUser直接作为主用户模型 - 添加
CustomUserManager:AbstractBaseUser必须搭配自定义管理器才能创建用户 - 使用
set_password()处理密码哈希,避免存储明文密码 - 补充
is_active、is_staff字段,满足Django权限体系要求
确保settings.py中已配置自定义用户模型:
AUTH_USER_MODEL = '你的应用名.CustomUser'
2. 编写自定义认证后端
在应用目录下新建backends.py,实现认证逻辑:
from django.contrib.auth.backends import BaseBackend from .models import CustomUser class CustomAuthBackend(BaseBackend): # 校验用户凭证 def authenticate(self, request, username=None, password=None, **kwargs): try: # 根据用户名查询用户 user = CustomUser.objects.get(user_name=username) # 校验密码(check_password自动对比哈希值) if user.check_password(password) and user.is_active: return user except CustomUser.DoesNotExist: return None # 通过用户ID获取用户对象(会话维持用) def get_user(self, user_id): try: return CustomUser.objects.get(pk=user_id) except CustomUser.DoesNotExist: return None
3. 配置Django启用自定义后端
在settings.py中添加认证后端路径:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', # 保留默认后端(可选) '你的应用名.backends.CustomAuthBackend', ]
4. 注册视图的密码处理
确保注册时使用create_user方法哈希密码,示例:
from django.shortcuts import redirect, render from .forms import RegistrationForm from .models import CustomUser def register(request): if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): # 从表单获取数据 user_data = { 'user_name': form.cleaned_data['user_name'], 'email': form.cleaned_data['email'], 'password': form.cleaned_data['password1'], 'first_name': form.cleaned_data['first_name'], 'last_name': form.cleaned_data['last_name'], } # 创建用户(自动哈希密码) CustomUser.objects.create_user(**user_data) return redirect('login') else: form = RegistrationForm() return render(request, 'register.html', {'form': form})
5. 使用默认登录视图
Django自带的LoginView可直接适配自定义后端,只需保证登录表单的username字段对应user_name即可。
内容的提问来源于stack exchange,提问作者Ali Alvi
相关产品推荐
相关产品推荐

