将用户帐户从Joomla迁移到Django

时间:2010-01-02 06:56:14

标签: django joomla data-migration

我正在检修我最初使用Joomla到Django的网站,我想知道我是否可以直接从Joomla导入用户记录(我主要担心的是用户密码,因为它们是加密的)。

4 个答案:

答案 0 :(得分:3)

是的,你可以,但你必须做一些工作。 Joomla将用户保留在某个特定的数据库表结构中,因此您必须将它们拉出并将它们插入到您在Django应用程序中创建的用户表中。至于加密,如果算法已知,它可能是保存在数据库中的哈希值,只要在Django应用程序中实现相同的哈希算法,就可以按原样传输它。

请记住:Django是一个比Joomla更普遍的'概念' - 它是一个编写Web应用程序的框架,因此理论上你甚至可以用它完全重新实现Joomla。

答案 1 :(得分:1)

我认为有三种方法可以解决这个问题:

1)你可以阅读joomla和django如何制作密码哈希并用脚本进行迁移
2)你可以自己制作authentication backend
3)您可以使用ETL tool

答案 2 :(得分:1)

Django中的Joomla用户(Django身份验证后端,从Joomla中填充用户)

一旦我需要在以Django编写的新API中使用现有的Joomla用户。 问题是我不能仅仅将Joomla用户复制到Django数据库中,因为:

  • Joomla密码哈希系统不同于Django。
  • J用户和D用户具有不同的字段集(这很容易解决,但仍然可以)

所以我改为为Django创建了一个自定义身份验证后端,现在我可以放心地说了

Django可以针对Joomla数据库对用户进行身份验证,而无需解密密码哈希或一次从Joomla DB复制所有用户。

算法:

  • 将Joomla数据库连接到Django项目
  • 创建JoomlaUser模型,以从Joomla数据库填充用户
  • 实现check_joomla_password()功能,与Joomla相同,用于验证用户密码
  • 添加自定义“ Joomla Auth Backend”,该功能可在首次登录时将每个用户从Joomla复制到Django

实施:

要了解发生了什么,您应该对Django有一定的经验。 必须根据您的django项目修改代码。 但是,代码是从工作项目中获取的,只需进行最小的更改, 并且应该可以轻松满足您的需求。

1。连接到Joomla DB:

DATABASES = {
    'default': {"your default DB settings"},

    'joomla_db': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {},
        'NAME': 'joomla_database_name',
        # Don't store passwords in the code, instead use env vars:
        'USER':     os.environ['joomla_db_user'],
        'PASSWORD': os.environ['joomla_db_pass'],
        'HOST': 'joomla_db_host, can be localhost or remote IP',
        'PORT': '3306',
    }
}

# add logging to see DB requests:
LOGGING = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'handlers': ['console'],
        },
    },
}

2。创建Joomla用户模型

  • 阅读https://docs.djangoproject.com/en/2.1/howto/legacy-databases/
  • 考虑在哪里保留新的“ Joomla用户”模型。 在我的项目中,我创建了'users'应用,自定义用户模型可以在其中运行, 然后将放置自定义的Joomla后端。
  • 检查用户如何存储在现有的Joomla数据库中: python manage.py inspectdb --database="joomla_db"
  • 查找并仔细检查用户表。
  • 添加到users/models.py
class JoomlaUser(models.Model):
    """ Represents our customer from the legacy Joomla database. """

    username = models.CharField(max_length=150, primary_key=True)
    email = models.CharField(max_length=100)
    password = models.CharField(max_length=100)
    # you can copy more fields from `inspectdb` output, 
    # but it's enough for the example

    class Meta:
        # joomla db user table. WARNING, your case can differs.
        db_table = 'live_users'
        # readonly 
        managed = False
        # tip for the database router
        app_label = "joomla_users"  

为确保JoomlaUser模型将使用正确的数据库,请添加database router

  1. 在存储“ settings.py”文件的项目文件夹中创建文件“ db_routers.py”:
# project_name/db_routers.py
class DbRouter:
    """this router makes sure that django uses legacy 'Joomla' database for models, that are stored there (JoomlaUser)"""
    def db_for_read(self, model, **kwargs):
        if model._meta.app_label == 'joomla_users':
            return 'joomla_db'
        return None

    def db_for_write(self, model, **kwargs):
        if model._meta.app_label == 'joomla_users':
            return 'joomla_db'
        return None
  1. 注册新路由器,为此,请添加settings.py
# ensure that Joomla users are populated from the right database:
DATABASE_ROUTERS = ['project_name.db_routers.DbRouter']

现在转到django shell ./manage.py shell并尝试填充一些用户,例如

>>> from users.models import JoomlaUser
>>> print(JoomlaUser.objects.get(username='someuser'))
JoomlaUser object (someuser)
>>> 

如果一切正常,请继续进行下一步。否则,请检查错误,修复设置等

3。检查Joomla用户密码

Joomla不会存储用户密码,但会存储密码哈希,例如 $2y$10$aoZ4/bA7pe.QvjTU0R5.IeFGYrGag/THGvgKpoTk6bTz6XNkY0F2e

从Joomla v3.2开始,使用BLOWFISH算法对用户密码进行哈希处理。

所以我下载了一个python河豚实现:

pip install bcrypt
echo bcrypt >> requirements.txt

并在users/backend.py中创建了Joomla密码检查功能:

def check_joomla_password(password, hashed):
    """
    Check if password matches the hashed password,
    using same hashing method (Blowfish) as Joomla >= 3.2

    If you get wrong results with this function, check that
    the Hash starts from prefix "$2y", otherwise it is 
    probably not a blowfish hash from Joomla.

    :return: True/False
    """
    import bcrypt
    if password is None:
        return False
    # bcrypt requires byte strings
    password = password.encode('utf-8')
    hashed = hashed.encode('utf-8')

    return hashed == bcrypt.hashpw(password, hashed)

旧版本警告! Joomla <3.2使用不同的哈希方法(md5 +盐), 因此此功能将无法使用。 在这种情况下,请阅读joomla password encryption 并在python中实现一个哈希检查器,它可能看起来像:

# WARNING - THIS FUNCTION NOT TESTED WITH REAL JOOMLA USERS
# and definitely has some errors
def check_old_joomla_password(password, hashed):
    from hashlib import md5
    password = password.encode('utf-8')
    hashed = hashed.encode('utf-8')
    if password is None:
        return False

    # check carefully this part:
    hash, salt = hashed.split(':')
    return hash == md5(password+salt).hexdigest()

很遗憾,我没有运行旧的Joomla实例,因此无法为您测试此功能。

4。 Joomla身份验证后端

现在您可以为Django创建一个Joomla身份验证后端。

  1. 了解如何修改django身份验证后端:https://docs.djangoproject.com/en/dev/topics/auth/customizing/

  2. project/settings.py中注册Jango(尚不存在)后端:

AUTHENTICATION_BACKENDS = [
    # Check if user already in the local DB
    # by using default django users backend
    'django.contrib.auth.backends.ModelBackend',

    # If user was not found among django users,
    # use Joomla backend, which:
    #   - search for user in Joomla DB
    #   - check joomla user password
    #   - copy joomla user into Django user.
    'users.backend.JoomlaBackend',
]
  1. users/backend.py中创建Joomla身份验证后端:
from django.contrib.auth.models import User
from .models import JoomlaUser

""" check password function we wrote before """
def check_joomla_password(password, hashed):
    ...


class JoomlaBackend:
    def authenticate(self, request, username=None, password=None):
        """
        IF joomla user exists AND password is correct:
            create django user
            return user object 
        ELSE:
            return None
        """
        try:
            joomla_user = JoomlaUser.objects.get(username=username)
        except JoomlaUser.DoesNotExist:
            return None
        if check_joomla_password(password, joomla_user.password):
            # Password is correct, let's create identical Django user:
            return User.objects.create_user(
                username=username,
                email=joomla_user.email,
                password=password,
                # any additional fields from the Joomla user:
                ...
            )

    # this method is required to match Django Auth Backend interface
    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

测试和文档

恭喜-现在,您来自旧Joomla网站的客户可以在新Django网站或rest api等上使用其凭据。

现在,添加适当的测试和文档以涵盖此新代码。 这是很棘手的逻辑,因此,如果您不编写测试文档(懒惰的家伙),那么维护项目将是您(或其他人)屁股上的痛苦。

亲切的问候, @ Dmytro Gierman

更新11.04.2019-已修复错误。

答案 3 :(得分:0)

Joomla(PHP)是一个CMS,而Django(Python)是一个Web框架。

我想知道这是否真的有可能。我现在可以得出的结论是不可能。但是有人可能对此有任何想法。

谢谢:)