Django 在初始登录时强制用户修改密码
环境
Windows 11 家庭版
Python 3.10.2
Django 4.0.2
可使用 venv
相关文章
Django 第1回:创建 Django 自定义用户模型
Django 第2回:在 Django 首次登录时强制更改密码 – 本次
Django 第3回:强制未在一定时间内更改密码的用户进行密码更改
Django 第4回:创建随机且带有效期的 URL,并由上级批准发行账号
Django 第5回:通过密码尝试次数锁定和基于随机且带有效期的 URL 进行本人确认解锁
背景 –
在Django中,当密码通过电子邮件发送时,存在一些不希望原封不动地使用的情况。(例如安全方面等)
在这种情况下,可以实现一个功能,在用户首次登录时强制要求更改密码。
在上一篇文章中,我们创建了一个自定义用户模型并准备了一个名为password_changed的参数。
这一次,我们还开发了一个中间件,当访问页面时,如果password_changed的值为False(默认值),我们将重定向到密码更改页面。
情况

第一步

请按以下方式进行记录。
import re
from django.http import HttpResponseRedirect
from users.models import User # 作成したCustom User Model
# https://office54.net/python/django/middleware-make-myself
class ForcePasswordChangeMiddleware:
"""
初期パスワードを初回のログオン時に強制的に変更させるMiddleware。
'password_changed'がFalseであれば、未変更とみなしパスワード変更ページにリダイレクト。
パスワード変更後は'password_changed'をTrueにする
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if re.match(r'/admin/password_change/done/?', request.path):
try:
# refererが'http://xxx.xxx.xxx.xxx:xx/admin/password_change/'かどうかを確認する
# すなわちpassword変更されたならば、Userステータスを更新する
# HOSTNAMEの場合は正規表現を変更してください
referer = request.environ.get('HTTP_REFERER')
print("referer:",referer)
if re.match(r'^https?://((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).*/admin/password_change/?', referer):
user = User.objects.get(email=request.user.email)
user.password_changed = True
user.save()
except:
pass
return response
def process_view(self, request, view_func, view_arts, view_kwargs):
# ログアウトは許可する
if re.match(r'^/admin/logout/?', request.path):
return
# 初回ログイン時にパスワード変更を強いる
if re.match(r'^/admin/?', request.path) and \
not re.match(r'^/admin/password_change/?', request.path):
try:
# password_changeがFalseであれば、パスワード変更ページにリダイレクト
# すなわち初回ログイン時にパスワード変更を強いる
password_changed = request.user.password_changed
if password_changed == False:
return HttpResponseRedirect('/admin/password_change/')
except:
pass
(2022/07/09:为了使其无论是http还是https都可以使用,修正了re.match的语法)
对以下内容进行汉语本地语言释义1。
def __call__(self, request):
...
在视图函数执行后,会调用该部分。
当密码修改完成后= 转到 /admin/password_change/done/,检查 HTTP_REFERER 是否为 http://xxx.xxx.xxx.xxx:xx/admin/password_change/。
如果IP地址和端口是域名,需要修改正则表达式。
另外,也可以更改 /admin/ 部分,所以如果进行了更改,这里也需要修改。
def process_view(self, request, view_func, view_arts, view_kwargs):
# ログアウトは許可する
if re.match(r'^/admin/logout/?', request.path):
return
# 初回ログイン時にパスワード変更を強いる
if re.match(r'^/admin/?', request.path) and \
...
在process_view函数中,在调用视图函数之前会被挂钩。
在页面转换之前,强制进行重定向(更改密码)。
第二步骤
将新创建的中间件添加到 settings.py 中。
MIDDLEWARE = [
'users.password_middleware.ForcePasswordChangeMiddleware', # 追加
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
解释2
‘users.password_middleware.ForcePasswordChangeMiddleware’表示”应用名.py文件名.类名”。为了在页面加载之前尽早处理,请将其添加到开头。
确认动作
1. 目前情况

2. 退出登录

3. 登录

4. 登录后 lù

5. 更改密码后

備註
通过定期执行password_changed.py,并将其值设为False,可以定期提醒用户更改密码,例如每三个月。至于定期处理的详细说明将在另一个机会介绍。
请你提供下面的参考
【Django】如何自己创建(自定义)中间件
【Django】中间件是什么(激活、结构、执行时机)
Django 第1篇:创建Django自定义用户模型
Django 第2篇:在首次登录时强制修改密码
Django 第3篇:对长时间不修改密码的用户强制进行密码修改
Django 第4篇:生成随机且带有效期的URL,经上级批准后发放账号
Django 第5篇:通过密码尝试次数锁定和使用随机且带有效期的URL进行身份确认解锁