如何在Python/Django中验证WordPress密码哈希以实现跨系统登录?
在Django中验证WordPress用户密码的正确方案
嘿,我明白你现在的困扰——想让Django站点用WordPress的密码登录,试了好几种方法都失败了对吧?核心问题其实是WordPress的哈希格式和Python库的兼容性问题,我给你整理一套可行的方案:
首先得明确:WordPress 6.8现在用的是PHP的password_hash()生成的bcrypt哈希,但它的哈希前缀是$2y$,而Python的bcrypt库默认只认$2a$或$2b$前缀;另外还有部分旧WordPress站点用的是$P$开头的phpass哈希,得兼容这两种情况。
步骤1:安装必要依赖
先把需要的Python库装上:
pip install bcrypt phpass mysqlclient # mysqlclient用来连接MySQL,用其他数据库可换对应库
步骤2:编写兼容两种哈希格式的验证函数
这个函数能自动识别WordPress的哈希类型,然后用对应的方法验证:
import bcrypt from phpass import PasswordHash def verify_wp_password(plain_password: str, wp_hash: str) -> bool: # 处理新的bcrypt格式(WordPress 5.6+默认用这个) if wp_hash.startswith('$2y$'): # 把$2y$替换成$2b$,bcrypt完全兼容这个格式 adjusted_hash = wp_hash.replace('$2y$', '$2b$').encode('utf-8') password_bytes = plain_password.encode('utf-8') # bcrypt对密码长度有限制,超过72字节会自动截断,手动截断更稳妥 if len(password_bytes) > 72: password_bytes = password_bytes[:72] try: return bcrypt.checkpw(password_bytes, adjusted_hash) except ValueError: return False # 处理旧的phpass格式(老版本WordPress用的) elif wp_hash.startswith('$P$'): phpass_hasher = PasswordHash() try: return phpass_hasher.verify(plain_password, wp_hash) except ValueError: return False # 未知哈希格式,直接返回验证失败 else: return False
步骤3:在Django中集成WP认证
你可以自定义一个Django认证后端,这样就能让Django用WP的密码来登录用户了:
# 在你的Django应用下创建backends.py文件 from django.contrib.auth.backends import BaseBackend from django.contrib.auth.models import User import MySQLdb class WordPressAuthBackend(BaseBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 连接WordPress的数据库,这里根据你的实际配置修改 db = MySQLdb.connect( host='localhost', # WP数据库地址 user='wp_db_user', # WP数据库用户名 passwd='wp_db_password', # WP数据库密码 db='wordpress_db' # WP数据库名称 ) cursor = db.cursor() # 查询WP用户表,拿到对应用户名的密码哈希和邮箱 cursor.execute("SELECT user_pass, user_email FROM wp_users WHERE user_login = %s", (username,)) user_data = cursor.fetchone() db.close() if not user_data: return None # 没找到对应用户 wp_hash, wp_email = user_data # 验证密码 if verify_wp_password(password, wp_hash): # 验证成功后,创建或获取Django本地用户(避免重复创建) try: django_user = User.objects.get(username=username) except User.DoesNotExist: # 从WP同步邮箱信息,设置不可用密码(因为用WP密码验证) django_user = User( username=username, email=wp_email ) django_user.set_unusable_password() django_user.save() return django_user return None def get_user(self, user_id): # 根据用户ID获取Django用户,必须实现这个方法 try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
然后在你的Django项目settings.py里添加这个认证后端:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', # 保留默认的Django认证后端 'your_app_name.backends.WordPressAuthBackend', # 替换成你的应用名 ]
解决你之前遇到的那些问题
- 为什么
bcrypt.verify()提示“not a valid bcrypt hash”?因为WP的哈希前缀是$2y$,bcrypt不识别,替换成$2b$就解决了。 - 为什么
phpass.verify()失败?如果是新的bcrypt哈希,phpass当然认不出来,所以要分格式处理。 - 密码长度超过72字节的问题:bcrypt本身会自动截断,但手动截断能避免一些潜在的兼容性问题,所以加上更稳妥。
内容的提问来源于stack exchange,提问作者tklodd
相关产品推荐
相关产品推荐

