IoT系统RPC登录场景:如何在Django哈希器前实现自定义哈希函数?
没问题,这个需求其实可以通过定制Django的密码哈希器来完美解决,不用去硬改make_password的源码——毕竟Django本身就提供了扩展密码处理流程的机制,咱们一步步来:
实现方式:自定义密码哈希器
Django的密码系统是基于**哈希器(Password Hasher)**工作的,我们可以继承它内置的哈希器(比如默认的PBKDF2PasswordHasher),重写核心方法,让它在执行常规哈希前先调用你的hash_used_by_RPC函数。
1. 编写自定义哈希器代码
在你的Django项目里找一个合适的app(比如专门处理用户逻辑的accounts),创建一个hashers.py文件,然后写入以下代码:
from django.contrib.auth.hashers import PBKDF2PasswordHasher # 替换成你实际的RPC哈希实现 def hash_used_by_RPC(password): # 举个例子,假设RPC用的是SHA256哈希(实际建议用符合安全标准的算法) import hashlib return hashlib.sha256(password.encode('utf-8')).hexdigest() class RPCPreHashPasswordHasher(PBKDF2PasswordHasher): # 自定义算法标识,必须唯一 algorithm = "rpc_pre_hash_pbkdf2" def encode(self, password, salt, iterations=None): # 第一步:先对明文密码执行RPC哈希 rpc_hashed_pwd = hash_used_by_RPC(password) # 第二步:把RPC哈希后的结果传给父类,执行Django常规的PBKDF2哈希 return super().encode(rpc_hashed_pwd, salt, iterations) def verify(self, password, encoded): # 验证时也要先做RPC哈希,再用父类的验证逻辑 rpc_hashed_pwd = hash_used_by_RPC(password) return super().verify(rpc_hashed_pwd, encoded)
2. 配置Django使用自定义哈希器
打开项目根目录的settings.py,找到PASSWORD_HASHERS配置项(如果没有就新增),把我们的自定义哈希器放在最前面,确保Django优先使用它:
PASSWORD_HASHERS = [ # 替换成你的哈希器实际路径,比如accounts.hashers.RPCPreHashPasswordHasher 'your_app_name.hashers.RPCPreHashPasswordHasher', # 保留Django默认的哈希器,用于兼容旧密码(如果有的话) 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', ]
3. 为什么不直接修改make_password?
Django的make_password函数底层是调用配置的哈希器的encode方法来生成密码哈希的,通过定制哈希器的方式:
- 完全符合Django的扩展规范,不用修改框架源码,更易维护
- 自动兼容Django的密码验证、密码升级等原生功能
- 你的两个密码验证函数都能直接正常工作:
djangos_pass_check:直接调用user.check_password(clearPassNoHash)即可,因为自定义哈希器的verify方法会自动先执行RPC哈希RPC_pass_check:传入的RpcHashPassword已经是RPC哈希后的结果,user.check_password会直接用父类的逻辑验证它和数据库中存储的哈希是否匹配
验证效果
当你在Django后台创建用户、或者用户注册设置密码时,Django会自动先对明文密码执行hash_used_by_RPC,再进行常规的PBKDF2哈希,最终把两次哈希后的结果存储到数据库。而验证时不管是传入明文密码还是RPC哈希后的密码,都能正确匹配。
内容的提问来源于stack exchange,提问作者BushLee




