我希望能够在用户设置中设置一个选项,强制他们在下次登录管理界面时更改密码。这可能吗?它将如何实现?我现在正在使用默认的身份验证模型,但不反对修改或更改它。感谢您的帮助。
最佳答案
我自己实际上正在这样做。您需要三个组件:用户配置文件(如果您的站点上尚未使用)、中间件组件和 pre_save 信号。
我的代码在一个名为“accounts”的应用中。
# myproject/accounts/models.py
from django.db import models
from django.db.models import signals
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
force_password_change = models.BooleanField(default=False)
def create_user_profile_signal(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
def password_change_signal(sender, instance, **kwargs):
try:
user = User.objects.get(username=instance.username)
if not user.password == instance.password:
profile = user.get_profile()
profile.force_password_change = False
profile.save()
except User.DoesNotExist:
pass
signals.pre_save.connect(password_change_signal, sender=User, dispatch_uid='accounts.models')
signals.post_save.connect(create_user_profile_signal, sender=User, dispatch_uid='accounts.models')
首先,我们创建一个带有 User 外键的 UserProfile。 force_password_change
bool 值,正如其名称所描述的,在您想要强制用户更改密码时为用户设置为 true。你可以在这里做任何事情。在我的组织中,我们还选择每 90 天实现一次强制更改,因此我还有一个 DateTimeField 来存储用户上次更改密码的时间。然后在 pre_save 信号 password_changed_signal
中设置它。
其次,我们有 create_user_profile_signal
。这主要是为了完整性而添加的。如果您现在刚刚将用户配置文件添加到您的项目中,您将需要一个 post_save 信号,该信号将在每次创建用户时创建一个 UserProfile。这样就完成了这项任务。
第三,我们有 password_changed_signal
。这是一个 pre_save 信号,因为在此过程中,用户表中的实际行尚未更新。因此,我们既可以访问以前的密码,也可以访问即将保存的新密码。如果两者不匹配,则意味着用户更改了密码,然后我们可以重置 force_password_change bool 值。这就是重点,您还需要处理您添加的任何其他内容,例如设置前面提到的 DateTimeField。
最后两行将这两个函数附加到它们相应的信号上。
如果您还没有,您还需要将以下行添加到项目的 settings.py
(更改应用标签和模型名称以匹配您的设置):
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
这涵盖了基础知识。现在我们需要一个中间件组件来检查 force_password_change
标志的状态(以及任何其他必要的检查)。
# myproject/accounts/middleware.py
from django.http import HttpResponseRedirect
import re
class PasswordChangeMiddleware:
def process_request(self, request):
if request.user.is_authenticated() and \
re.match(r'^/admin/?', request.path) and \
not re.match(r'^/admin/password_change/?', request.path):
profile = request.user.get_profile()
if profile.force_password_change:
return HttpResponseRedirect('/admin/password_change/')
这个非常简单的中间件 Hook 到页面加载过程的 process_request
阶段。它会检查 1) 用户已经登录,2) 他们正在尝试访问管理员中的某个页面,以及 3) 他们正在访问的页面不是密码更改页面本身(否则,你会得到一个无限循环重定向)。如果所有这些都为真并且 force_password_change
标志已设置为 True
,则用户将被重定向到密码更改页面。在更改密码(触发前面讨论的 pre_save 信号)之前,他们将无法导航到其他任何地方。
最后,您只需将此中间件添加到项目的 settings.py
中(同样,根据需要更改导入路径):
MIDDLEWARE_CLASSES = (
# Other middleware here
'myproject.accounts.middleware.PasswordChangeMiddleware',
)
关于python - 是否可以在 django admin 中实现 "change password at next logon"类型的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2093593/