跳转到主要内容

Django使用passlib的hasher

项目描述

django-hashers-passlib[-revived]

⚠️ 原始项目 django-hashers-passlib 已停止维护。它已被分叉、更新并重命名为 django-hashers-passlib-revived。您可能在这里以及代码的各个部分仍然找到术语 django-hashers-passlib


django-hashers-passlib-revived 的目的是使 passlib 提供的密码散列方案在 Django 中可用。与 passlib 的 passlib.ext.django 不同,它不替换 Django 的 密码管理系统,而是提供标准散列器,可以添加到 PASSWORD_HASHERS 设置以使用 passlib 提供的散列方案。

此模块有两个主要用途

  1. 您希望从现有的应用程序中导入密码散列到您的Django数据库。
  2. 您希望在将来将密码散列导出到不同的应用程序。

安装

此模块可通过pip获取,使用以下命令安装:

pip install django-hashers-passlib-revived

兼容性矩阵

Py/Dj 3.8 3.9 3.10 3.11 3.12
3.2 (LTS)
4.0
4.1
4.2 (LTS)
5.0

此外,passlib>=1.7"是依赖项。

入门

此模块支持passlib支持的几乎所有散列(某些散列最初必须进行转换 - 见下文)。如果要让您的Django项目应用理解passlib提供的散列,只需将散列器添加到PASSWORD_HASHERS设置中。请注意,第一个值是默认散列器,因此如果您想将这些散列之一存储为新用户密码,请将散列添加到列表的开头

PASSWORD_HASHERS = [
    # new user passwords should be stored in the phpass format
    'hashers_passlib.phpass',

    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    # ... other Django hashers

    # We also want to add some users from say mssql2000 (who wouldn't?)
    'hashers_passlib.mssql2000',
]

几乎每个passlib模块都有一个与名称相同的散列器,有关完整列表,请参阅“支持的散列”。

您还可以为不同的散列算法配置默认参数,例如配置不同轮次的pbkdf2_sha256

PASSLIB_KEYWORDS = {
    'pbkdf2_sha256': {
        'rounds': 32000,
    },
}

passlib的文档包含可用参数的列表。

导入/导出

Django规定了存储密码的方案(见Django如何存储密码。某些散列仅通过添加散列名称来存储,其他散列几乎适合该方案,只需移除其前面的$

如果您想从其他应用程序导入散列到Django的散列编码方案(有关详细信息,请参阅下文“内部工作方式”),每个散列器都有一个from_orig()to_orig()方法,这允许导入/导出散列。因此,从不同的系统导入用户只是调用正确散列器的from_orig()并将其保存到Django的User模型的password字段。以下是一个简单的示例

# Lets import a phpass (WordPress, phpBB3, ...) hash. This assumes that you have 'hashers_passlib.phpass' in
# your PASSWORD_HASHERS setting.

from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import get_hasher

User = get_user_model()  # get any custom user model

hasher = get_hasher('phpass')

# you got this from i.e. a WordPress database:
raw_hashes = {
    'joe': '$P$EnOjUf5ie1AeWMHpw1dqHUQYHAIBe41',
    'jane': '$P$E6UROQJscRzZ3ve2hoIFZ1OcjBA1W10',
}

for username, hash in raw_hashes.items():
    user = User.objects.create(username=username)
    user.password = hasher.from_orig(hash)
    user.save()

现在,“joe”和“jane”可以使用他们的旧用户名和密码登录。

如果您想再次将具有phpass散列的用户导出到WordPress数据库,您可以简单地获取原始散列(为了简单起见,我们在这里将所有内容打印到stdout)

from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import get_hasher

User = get_user_model()  # get any custom user model

hasher = get_hasher('phpass')

for user in User.objects.filter(password__startswith='phpass$'):
    orig_hash = hasher.to_orig(user.password)
    print('%s has hash "%s"' % (user.username, orig_hash))

支持的散列

此模块为passlib提供的几乎所有散列方案提供了散列器 - 但请记住,您必须首先使用散列器的from_orig()方法导入它们才能使用。某些散列必须首先进行转换(见下文),并且不支持少数几个旧的散列。所有密码散列器都具有与它们包装的passlib散列器相同的类名,并位于hashers_passlib模块中。因此,要启用对例如sha1_crypt散列的支持,请将hashers_passlib.sha1_crypt添加到您的PASSWORD_HASHERS Django设置中。

警告:某些散列的长度超过了Django提供的标准用户模型中的128个字符。您必须指定一个至少有256个字符的自定义用户模型(对于hex_sha512pbkdf2_sha512scramsha512_crypt)或至少有384个字符的(对于grub_pbkdf2_sha512)。

以下算法受到支持:des_cryptbsdi_cryptbigcryptcrypt16md5_cryptsha1_cryptsun_md5_cryptsha256_cryptsha512_cryptapr_md5_cryptbcrypt_sha256phpasspbkdf2_<digest>dlitz_pbkdf2_sha1cta_pbkdf2_sha1scramldap_salted_md5ldap_salted_sha1atlassian_pbkdf2_sha1fshpmssql2000mssql2005mysql323mysql41oracle11lmhashnthashcisco_pixcisco_type7grub_pbkdf2_sha512hex_{md4,sha256,sha512}argon2scrypt

大多数哈希将以简单的前缀 <algorithm>$ 保存,其中 "<algorithm>" 是散列器的名称。唯一的例外是一些哈希(apr_md5_cryptbcrypt_sha256pbkdf2_<digest>scram),它们几乎已经符合 Django 的哈希方案,只需去掉开头的 $

注意:一些哈希(bcrypt_sha256pbkdf2_<digest>、...)看起来与 Django 提供的非常相似,但实际上是不同的算法。

通过转换支持的哈希

有些哈希方案实际上只是不同哈希方案的微小变化。例如,bsd_nthash 只是一个普通的 nthash,前面加上 $3$$,而 ldap_md5 只是前面加上 {MD5} 的纯 MD5 哈希,这已经由 Django 支持。

为了避免代码重复,此模块不提供这些方案的密码散列器,而是在 hashers_passlib.converters 下提供转换器。转换后的哈希可以被不同的散列器或 Django 提供的散列器读取。

如果您想导入 bsd_nthash 哈希,您可以通过手动删除标识符或使用转换器来实现。

# Lets import bsd_nthash hashes as plain nthash hashes. This assumes you have
# have 'hashers_passlib.nthash' in your PASSWORD_HASHERS setting.

from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import get_hasher

from hashers_passlib.converters import bsd_nthash

conv = bsd_nthash()

raw_hashes = {
    'joe': '$3$$baac3929fabc9e6dcd32421ba94a84d4',
}

for username, hash in raw_hashes.items():
    user = User.objects.create(username=username)

    # convert bsd_nthash to plain nthash:
    user.password = converter.from_orig(hash)
    user.save()

以下转换器在 hashers_passlib.converters 下可用,它们可用于从原始方案转换为其他方案

说明
bcrypt BCryptPasswordHasher 转换为 Django 散列器支持的 bcrypt 哈希。
bsd_nthash nthash 从 bsd_nthash 转换到 nthash,反之亦然。
ldap_md5 UnsaltedMD5PasswordHasher 转换为 Django 支持的纯 MD5 哈希。
ldap_sha1 UnsaltedSHA1PasswordHasher 转换为 Django 支持的纯 SHA1 哈希。
ldap_hex_md5 UnsaltedMD5PasswordHasher 转换为 Django 支持的纯 MD5 哈希。
ldap_hex_sha1 UnsaltedSHA1PasswordHasher 转换为 Django 支持的纯 SHA1 哈希。
ldap_{crypt} 各种 转换为它们的非LDAP对应项(例如,ldap_des_crypt 转换为普通的 des_crypt 哈希)。
ldap_bcrypt BCryptPasswordHasher 与其他 ldap_{crypt} 方案不同,ldap_bcrypt 哈希被转换为 Django 自带的 BCrypt 哈希器所理解的格式。
ldap_pbkdf2_{digest} pbkdf2_{digest} 转换为它们的非LDAP对应项。

不受支持的哈希

某些哈希不受支持,因为它们需要用户名来生成盐: postgres_md5oracle10msdccmsdcc2

内部工作原理

Django 的密码管理系统以与 passlib 所称的 模块化加密格式非常相似但仍有区别的格式存储密码

<algorithm>$<content>

... 其中 "<algorithm>" 是用于选择应处理哈希的哈希器类的标识符。与模块化加密格式的唯一区别是它缺少前导的 $ 符号。注意,中间的 $ 是一个强制分隔符。

此模块修改哈希方案,以便在将其存储到数据库之前符合此方案。这些修改是完全可逆的——实际上,此模块依赖于可逆性,我们的哈希器不会以任何其他方式工作。根据原始哈希方案,哈希以以下几种方式之一进行修改

  1. 一些旧的、不安全的哈希需要用户名来编码哈希。Django 的哈希器不接收用户名,因此它们与该模块不兼容,也不受支持。
  2. Passlib 的一些哈希已经由 Django 支持,并且此处没有重复功能。
  3. 一些哈希方案实际上是不同方案的微小修改,我们在此情况下提供转换器。
  4. 一些哈希已经几乎符合 Django 的方案,并且具有相当独特的标识符,它们只是去除了前导的 $
  5. 所有其他哈希(占绝大多数!)只是添加了 <identifier>$。这与 Django 对 bcrypt 哈希的处理方式相同。

本地开发

使用 Poetry 安装项目和其开发依赖项

pip install poetry
poetry install

您可以使用 pytest 调用测试套件

poetry run pytest

您可以使用 Tox 测试所有支持的 Django 和 Python 版本组合

pip install tox
tox p

变更日志

2.0 (WIP)

原始项目 django-hashes-passlib 已由原始开发者停止维护。该项目已被分叉并重命名为 django-hashers-passlib-revived

  • 添加了对 Django 4.1、4.2 和 5.0 的支持。
  • 添加了对 Python 3.11 和 3.12 的支持。
  • 为所有内容添加了类型。
  • 使用 Poetry 为本地开发环境。
  • 总体代码清理和现代化。

1.0.0 (从未发布)

  • 添加了对 Django 3.2 和 Django 4.0 的支持。
  • 添加了对 Python 3.7 - 3.10 的支持。
  • 放弃了对过时 Django 版本 1.8、1.10 和 1.11 的支持。
  • 放弃了对已弃用的 Python 版本(2.7 - 3.6)的支持。
  • 添加了 argon2dargon2id 哈希器。我们建议如果需要,添加所有 argon2 哈希器。
  • 将 CI 测试切换到 GitHub Actions。
  • 现代化项目设置(pyproject.tomlsetup.cfg 等)。
  • 将 black 和 pylint 添加到 linters/formatters 套件。

0.4 (2017年11月19日)

  • 支持 passlib 1.7。
  • 添加了 argon2 和 scrypt 哈希器。
  • 通过 PASSLIB_KEYWORDS 设置配置哈希参数。
  • 添加了类似于 Django 的 VERSIONget_version()
  • 通过 Travis 集成运行测试套件,使用 Python 2.7、3.4+ 以及 Django 当前所有支持的版本。
  • 更新 setup.py 中的 python 版本分类器。
  • 还上传了 wheel。

0.3 (2015年12月5日)

  • 要求 Python3>=3.4
  • 依赖于 Django>=1.8
  • 更新 passlib 和 bcrypt 依赖项。

0.2 (2014年3月22日)

  • 删除 distribute_setup.py。
  • 为所有哈希器实现通用的 safe_summary() 方法。
  • 将 bcrypt 添加到 requirements.txt。
  • 现在向 setup.py 报告的版本与从 git 仓库执行时相同的 git describe
  • 添加 version setup.py 命令。
  • 修复 Python 3 中的 ldap_md5ldap_sha1 转换器。

0.1 (2014年1月1日)

  • 初始发布。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码发行版

django_hashers_passlib_revived-2.0.tar.gz (29.6 kB 查看哈希值)

上传时间 源代码

构建发行版

django_hashers_passlib_revived-2.0-py3-none-any.whl (26.7 kB 查看哈希值)

上传时间 Python 3

由以下提供支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面