Django扩展User类角色冲突及讲师账号密码锁定问题求助
问题解决与代码优化
一、超级用户角色冲突问题
当前自定义User类中,超级用户(is_superuser=True)可能被标记为Alumni角色,导致权限逻辑混乱,可通过以下方式解决:
1. 自动绑定超级用户与Admin角色
在save方法中添加逻辑,当用户被设置为超级用户时,自动将其角色设为Admin,避免手动配置错误:
def save(self, *args, **kwargs): # 超级用户自动关联Admin角色 if self.is_superuser: self.role = User.Role.ADMIN # 讲师默认密码逻辑保留 if self.role == User.Role.LECTURER and not self.password: self.set_password('ou@123') super().save(*args, **kwargs)
2. 后台Admin防误操作优化(可选)
在Admin管理界面中,禁用超级用户的角色编辑权限,防止手动修改导致冲突:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import User class CustomUserAdmin(UserAdmin): def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) # 超级用户的角色字段设为不可编辑 if obj and obj.is_superuser: form.base_fields['role'].disabled = True return form admin.site.register(User, CustomUserAdmin)
二、讲师账号密码过期锁定功能优化
原代码存在两个核心问题:仅依赖date_joined无法区分用户是否修改过密码;无自动触发检查的时机。以下是优化方案:
1. 添加密码更新时间字段
在User类中新增password_updated字段,记录最后一次修改密码的时间:
from django.utils import timezone class User(AbstractUser): # 原有字段保留... password_updated = models.DateTimeField(null=True, blank=True) def save(self, *args, **kwargs): # 超级用户角色绑定逻辑 if self.is_superuser: self.role = User.Role.ADMIN # 讲师创建时设置默认密码并记录更新时间 if self.role == User.Role.LECTURER and not self.password: self.set_password('ou@123') self.password_updated = timezone.now() # 密码变更时更新记录时间 if self.pk: old_user = User.objects.get(pk=self.pk) if old_user.password != self.password: self.password_updated = timezone.now() super().save(*args, **kwargs)
2. 完善密码过期检查逻辑
修改check_password_expiry方法,仅在讲师未修改过密码且超过24小时的情况下锁定账号:
def check_password_expiry(self): if self.role != User.Role.LECTURER: return # 未修改过密码且超过24小时则锁定 if self.password_updated and (timezone.now() - self.password_updated) > timedelta(hours=24): self.is_active = False self.save()
3. 设置登录触发检查
通过DRF自定义认证类,在用户登录时自动执行密码过期检查:
from rest_framework.authentication import TokenAuthentication from rest_framework import exceptions class CustomTokenAuthentication(TokenAuthentication): def authenticate_credentials(self, key): user, token = super().authenticate_credentials(key) # 登录时检查密码过期状态 user.check_password_expiry() if not user.is_active: raise exceptions.AuthenticationFailed("账号已锁定,请联系管理员启用") return (user, token)
在settings.py中配置DRF认证:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'your_app_name.authentication.CustomTokenAuthentication', # 其他认证类保留... ] }
4. 管理员重新启用账号逻辑
管理员在后台启用讲师账号时,自动重置默认密码并更新时间:
class CustomUserAdmin(UserAdmin): # 原有代码保留... def save_model(self, request, obj, form, change): # 启用讲师账号时重置默认密码 if obj.role == User.Role.LECTURER and 'is_active' in form.changed_data and obj.is_active: obj.set_password('ou@123') obj.password_updated = timezone.now() super().save_model(request, obj, form, change)
内容的提问来源于stack exchange,提问作者Trần Lệ Lân
相关产品推荐
相关产品推荐

