如何在Django中用pbkdf2_sha256哈希MySQL存量明文密码并兼容老用户登录
处理存量明文密码,让老用户无需重新注册即可登录
我是Django新手,现在有一批存储为明文的用户密码,需要编写脚本对这些密码进行哈希处理,同时要让存量老用户不用创建新账号就能登录。我已经实现了新用户的注册和登录功能,代码如下:
@admin_login_required def add_emp(request): if request.method == 'POST': user_name = request.POST['user_name'] user_email = request.POST['user_email'] user_otj = request.POST['user_otj'] user_password = pwo.generate() user_password1 = make_password(user_password) empObj = User.objects.create(user_name=user_name, user_email=user_email, user_password=user_password1, user_otj=user_otj) if empObj: subject = 'Advanced Analytics Portal - Login Info' message = f'Name : {user_name}, \\n Email : {user_email}, \\n Password : {user_password} \\n FROM - AA Portal' email_from = settings.EMAIL_HOST_USER send_mail(subject, message, email_from, [user_email]) messages.success(request, "Employee was added successfully!") return HttpResponseRedirect('/create-emp') else: messages.error(request, "Some error was occurred!") return HttpResponseRedirect('/create-emp') return render(request, 'AddEmp.html') def user_login(request): if request.method == "POST": user_email = request.POST['user_email'] user_password = request.POST['user_password'] user_details = User.objects.filter(user_email=user_email).first() if user_details and check_password(user_password, user_details.user_password): request.session['logged_in'] = True request.session['user_email'] = user_details.user_email request.session['u_id'] = user_details.user_email request.session['user_name'] = user_details.user_name request.session['u_type'] = "emp" return HttpResponseRedirect('/user_index') else: return render(request, 'EmpLogin.html', {'msg': "0"}) else: return render(request, 'EmpLogin.html')
解决方案
一、修改登录逻辑,兼容明文与哈希密码
现在的登录逻辑只支持哈希密码验证,需要调整为:先尝试哈希密码验证,失败后再匹配明文密码,若明文匹配成功,立即将密码哈希后更新到数据库,确保下次登录走正常哈希流程。
修改后的user_login函数:
def user_login(request): if request.method == "POST": user_email = request.POST['user_email'] user_password = request.POST['user_password'] user_details = User.objects.filter(user_email=user_email).first() if user_details: # 优先验证哈希密码(新用户或已更新的老用户) if check_password(user_password, user_details.user_password): # 设置会话并跳转 request.session['logged_in'] = True request.session['user_email'] = user_details.user_email request.session['u_id'] = user_details.user_email request.session['user_name'] = user_details.user_name request.session['u_type'] = "emp" return HttpResponseRedirect('/user_index') else: # 哈希验证失败,尝试明文匹配 if user_details.user_password == user_password: # 明文匹配成功,更新为哈希密码 hashed_pw = make_password(user_password) user_details.user_password = hashed_pw user_details.save() # 设置会话并跳转 request.session['logged_in'] = True request.session['user_email'] = user_details.user_email request.session['u_id'] = user_details.user_email request.session['user_name'] = user_details.user_name request.session['u_type'] = "emp" return HttpResponseRedirect('/user_index') else: # 两种验证都失败 return render(request, 'EmpLogin.html', {'msg': "0"}) else: # 用户不存在 return render(request, 'EmpLogin.html', {'msg': "0"}) else: return render(request, 'EmpLogin.html')
二、批量转换明文密码(主动处理所有存量用户)
如果不想等用户登录时才更新密码,可以通过以下方式批量转换:
方法1:使用Django Shell执行
进入项目根目录,运行:
python manage.py shell
然后执行代码:
from django.contrib.auth.hashers import make_password from your_app.models import User # 替换为你的User模型所在app名 # 筛选出所有非哈希格式的用户(Django哈希密码以pbkdf2_sha256$、bcrypt$、argon2$开头) plain_pw_users = User.objects.exclude(user_password__startswith='pbkdf2_sha256$').exclude(user_password__startswith='bcrypt$').exclude(user_password__startswith='argon2$') for user in plain_pw_users: user.user_password = make_password(user.user_password) user.save() print(f"已更新用户 {user.user_email} 的密码为哈希格式")
方法2:编写自定义管理命令
- 在你的app下创建
management/commands目录(无则新建),创建convert_plain_passwords.py文件:
from django.core.management.base import BaseCommand from django.contrib.auth.hashers import make_password from your_app.models import User # 替换为你的User模型路径 class Command(BaseCommand): help = '批量将明文用户密码转换为哈希格式' def handle(self, *args, **options): plain_pw_users = User.objects.exclude( user_password__startswith='pbkdf2_sha256$' ).exclude( user_password__startswith='bcrypt$' ).exclude( user_password__startswith='argon2$' ) count = 0 for user in plain_pw_users: user.user_password = make_password(user.user_password) user.save() count += 1 self.stdout.write(self.style.SUCCESS(f'成功更新 {count} 个用户的密码为哈希格式'))
- 在终端运行命令:
python manage.py convert_plain_passwords
三、后续注意事项
- 保持现有新用户注册逻辑不变(已用
make_password处理密码,符合规范) - 批量转换后,建议测试几个老用户的登录流程,确保正常
- 后续绝对禁止存储明文密码,所有密码入库前必须经过哈希处理
内容的提问来源于stack exchange,提问作者JHS99
相关产品推荐
相关产品推荐

