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(默认值),我们将重定向到密码更改页面。

情况

image.png

第一步

image.png

请按以下方式进行记录。

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. 目前情况

image.png

2. 退出登录

image.png

3. 登录

image.png

4. 登录后 lù

image.png

5. 更改密码后

image.png

備註

通过定期执行password_changed.py,并将其值设为False,可以定期提醒用户更改密码,例如每三个月。至于定期处理的详细说明将在另一个机会介绍。

请你提供下面的参考

【Django】如何自己创建(自定义)中间件
【Django】中间件是什么(激活、结构、执行时机)
Django 第1篇:创建Django自定义用户模型
Django 第2篇:在首次登录时强制修改密码
Django 第3篇:对长时间不修改密码的用户强制进行密码修改
Django 第4篇:生成随机且带有效期的URL,经上级批准后发放账号
Django 第5篇:通过密码尝试次数锁定和使用随机且带有效期的URL进行身份确认解锁

bannerAds