我正在检修我最初使用Joomla到Django的网站,我想知道我是否可以直接从Joomla导入用户记录(我主要担心的是用户密码,因为它们是加密的)。
答案 0 :(得分:3)
是的,你可以,但你必须做一些工作。 Joomla将用户保留在某个特定的数据库表结构中,因此您必须将它们拉出并将它们插入到您在Django应用程序中创建的用户表中。至于加密,如果算法已知,它可能是保存在数据库中的哈希值,只要在Django应用程序中实现相同的哈希算法,就可以按原样传输它。
请记住:Django是一个比Joomla更普遍的'概念' - 它是一个编写Web应用程序的框架,因此理论上你甚至可以用它完全重新实现Joomla。
答案 1 :(得分:1)
我认为有三种方法可以解决这个问题:
1)你可以阅读joomla和django如何制作密码哈希并用脚本进行迁移
2)你可以自己制作authentication backend
3)您可以使用ETL tool
答案 2 :(得分:1)
一旦我需要在以Django编写的新API中使用现有的Joomla用户。 问题是我不能仅仅将Joomla用户复制到Django数据库中,因为:
所以我改为为Django创建了一个自定义身份验证后端,现在我可以放心地说了
Django可以针对Joomla数据库对用户进行身份验证,而无需解密密码哈希或一次从Joomla DB复制所有用户。
check_joomla_password()
功能,与Joomla相同,用于验证用户密码要了解发生了什么,您应该对Django有一定的经验。 必须根据您的django项目修改代码。 但是,代码是从工作项目中获取的,只需进行最小的更改, 并且应该可以轻松满足您的需求。
/project_name/settings.py
: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'],
},
},
}
'users'
应用,自定义用户模型可以在其中运行,
然后将放置自定义的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:
# 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
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)
>>>
如果一切正常,请继续进行下一步。否则,请检查错误,修复设置等
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实例,因此无法为您测试此功能。
现在您可以为Django创建一个Joomla身份验证后端。
了解如何修改django身份验证后端:https://docs.djangoproject.com/en/dev/topics/auth/customizing/
在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',
]
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框架。
我想知道这是否真的有可能。我现在可以得出的结论是不可能。但是有人可能对此有任何想法。
谢谢:)