You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:12:29