Текущая информация о системе хранения паролей Discourse доступна по адресу discourse/docs/SECURITY.md at main · discourse/discourse · GitHub. На момент написания мы используем PBKDF2-SHA256 с 600 000 итерациями.
В некоторых случаях вам может потребоваться экспортировать все хешированные пароли из Discourse и импортировать их в другую систему. Например, вы можете мигрировать с встроенной аутентификации Discourse на кастомную систему единого входа (SSO). Помните, что извлечь исходные пароли из базы данных невозможно, поэтому целевая система должна поддерживать тот же алгоритм хеширования с теми же параметрами.
Данные паролей хранятся в таблице user_passwords, которая содержит столбцы password_hash, password_salt и password_algorithm. Столбец password_algorithm хранит полный префикс алгоритма PHC (например, $pbkdf2-sha256$i=600000,l=32$), который может различаться для разных пользователей, если количество итераций со временем увеличивалось.
Вы можете использовать Data Explorer для экспорта информации в машиночитаемом формате:
SELECT users.id, users.username, up.password_salt, up.password_hash, up.password_algorithm
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Это экспортирует данные в нативном формате Discourse. Соль закодирована в шестнадцатеричном виде, хеш пароля также закодирован в шестнадцатеричном виде.
Некоторые внешние системы поддерживают формат строк PHC, который представляет собой универсальный способ представления результата хеширования паролей для различных алгоритмов. Для pbkdf2-sha256 такая строка содержит тип алгоритма, количество итераций, соль в base64 и хеш в base64. К счастью, Postgres может обработать всё это за один запрос.
Чтобы сгенерировать строки PHC для каждого пользователя Discourse, вы можете использовать запрос Data Explorer следующего вида:
SELECT users.id, users.username,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as phc
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Если вы используете Auth0, используйте следующий запрос:
SELECT
user_emails.email,
users.active as email_verified,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as password_hash
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
INNER JOIN user_emails
ON users.id = user_emails.user_id
AND user_emails.primary IS TRUE
AND users.id > 0