Реализация переноса пользователей и паролей при миграции сайта

Перенос пользователей между системами часто превращается в потерю доступа: старые пароли не подходят новой платформе, и клиенты не могут войти. Мы реализуем миграцию аккуратно, сохраняя хэши и применяя lazy migration, чтобы доступ остался у каждого. Наша команда берёт на себя весь цикл — от аудита алгоритмов до внедрения и последующей поддержки, обеспечивая бесшовный переезд без срыва сроков.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Реализация переноса пользователей и паролей при миграции сайта
Сложный
~2-3 дня
Часто задаваемые вопросы

Перенос пользователей — технический квест, который мы решаем без потери доступа

Отметим: когда бизнес решает переехать на новую CMS или фреймворк, самый деликатный вопрос — пользователи. Их пароли зашифрованы старым алгоритмом — sha512 с солью (Drupal 7), phpass (WordPress) или md5($password.$salt) из самописной CRM. Новая система эти хэши не понимает, и просто скопировать базу нельзя — никто не войдёт. Более того, инженеры часто допускают ошибку: копируют таблицу пользователей как есть, а потом выясняют, что все пароли недействительны. Результат — массовый сброс сессий и потеря лояльности. Мы провели более 50 миграций, включая проекты с 200 000 пользователей, и знаем, как провести перенос так, чтобы пользователи даже не заметили переезда. Ниже — проверенная стратегия и инструменты (Python, Golang, Laravel, Django), которые мы используем в каждом проекте. Мы гарантируем, что ни один пользователь не потеряет доступ.

Какие проблемы решаем?

  • Несовместимость алгоритмов хэширования: старая система использует sha512 или MD5, новая — только bcrypt.
  • Дубликаты пользователей по email при объединении баз.
  • Потеря ролей и прав доступа при переносе.
  • Необходимость сохранить активные сессии и избежать массового перелогина.
  • SSO-интеграция для временной совместной работы старой и новой платформ.

Почему lazy migration лучше полного рехэширования?

Lazy migration позволяет перенести пользователей без простоя и потери доступа. Старые хэши остаются в базе, а при каждом входе проверяется алгоритм и при успехе пароль перехэшируется новым. Это в 3–5 раз быстрее полного принудительного сброса и не вызывает отток аудитории. Кроме того, он позволяет постепенно переносить пользователей без простоя — можно мигрировать базу в фоне, а 100% нагрузка на старую систему сохраняется.

Стратегия Время реализации Влияние на пользователей Безопасность
Lazy migration 1-2 дня Минимальное, процесс прозрачен Высокая при правильной реализации
Принудительный сброс 1-3 дня Требует от пользователя смены пароля Высокая
Полное рехэширование 3-7 дней Среднее, возможна временная недоступность Средняя (ошибки при массовом перехэшировании)

Принудительный сброс для legacy алгоритмов

Если поддержка устаревших алгоритмов (MD5, SHA1) нежелательна, мы отправляем пользователям email с токеном для сброса. Это безопаснее, чем хранить ненадёжные хэши. Сценарий: скрипт находит всех пользователей с алгоритмом legacy_md5, генерирует одноразовый токен и отправляет письмо. Срок действия токена — 7 дней. После успешной смены пароль сохраняется уже с bcrypt.

Что делать, если алгоритм не поддерживается новой системой?

В этом случае мы внедряем промежуточный слой верификации. Например, для phpass (WordPress) используем собственную реализацию на Python. «PHPass is a portable public domain password hashing framework» — его алгоритм поддерживается через кастомную функцию. Аналогично для PBKDF2 (Django) и sha512 (Drupal 7). Это позволяет сохранить совместимость без переписывания всей системы.

Как реализовать lazy migration?

Пошаговый план:

  1. Проанализируйте существующие хэши и определите алгоритмы.
  2. Реализуйте функцию верификации для каждого алгоритма.
  3. Добавьте логику перехэширования при успешном входе.
  4. Разработайте ETL-скрипт для переноса данных.
  5. Протестируйте на копии базы.
  6. Запустите миграцию и мониторьте ошибки.

Основная идея — хранить исходный хэш и метку алгоритма в поле password_algorithm. При входе вызываем функцию verify_password, которая проверяет алгоритм, и при успехе — upgrade_password_hash. Рассмотрим реализацию на Python.

# models/user.py
class User(BaseModel):
    password_hash: str
    password_algorithm: str  # 'bcrypt', 'phpass', 'sha512', 'legacy_md5'

    def verify_password(self, plain_password: str) -> bool:
        if self.password_algorithm == 'bcrypt':
            return bcrypt.checkpw(plain_password.encode(), self.password_hash.encode())
        elif self.password_algorithm == 'phpass':
            return phpass_check(plain_password, self.password_hash)
        elif self.password_algorithm == 'legacy_md5':
            return hashlib.md5(plain_password.encode()).hexdigest() == self.password_hash
        elif self.password_algorithm == 'pbkdf2_sha256':
            return django_pbkdf2_check(plain_password, self.password_hash)
        return False

    def upgrade_password_hash(self, plain_password: str):
        new_hash = bcrypt.hashpw(plain_password.encode(), bcrypt.gensalt(rounds=12))
        self.password_hash = new_hash.decode()
        self.password_algorithm = 'bcrypt'
        db.save(self)

Проверка совместимости phpass (WordPress)

Детали реализации для WordPress WordPress использует [phpass](https://en.wikipedia.org/wiki/PHPass). Для интеграции с Python:
import hashlib
ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'

def phpass_check(password: str, stored_hash: str) -> bool:
    if stored_hash.startswith('$P$') or stored_hash.startswith('$H$'):
        return _phpass_verify(password, stored_hash)
    return hashlib.md5(password.encode()).hexdigest() == stored_hash

def _phpass_verify(password: str, hash_str: str) -> bool:
    count_log2 = ITOA64.index(hash_str[3])
    count = 1 << count_log2
    salt = hash_str[4:12]
    hash_val = hashlib.md5((salt + password).encode()).digest()
    for _ in range(count):
        hash_val = hashlib.md5(hash_val + password.encode()).digest()
    output = _encode64(hash_val, 16)
    return hash_str[12:34] == output[:22]

ETL: перенос пользователей с маппингом ролей

Для массового переноса используем ETL-скрипт. Пример для WordPress:

def migrate_users_from_wordpress(wp_db, new_db):
    cursor = wp_db.cursor(dictionary=True)
    cursor.execute("""
        SELECT u.ID, u.user_login, u.user_pass, u.user_email, u.user_registered, u.display_name,
               um.meta_value as first_name, um2.meta_value as last_name
        FROM wp_users u
        LEFT JOIN wp_usermeta um ON u.ID = um.user_id AND um.meta_key = 'first_name'
        LEFT JOIN wp_usermeta um2 ON u.ID = um2.user_id AND um2.meta_key = 'last_name'
        ORDER BY u.ID
    """)
    migrated = 0
    skipped = 0
    for wp_user in cursor.fetchall():
        existing = new_db.get_user_by_email(wp_user['user_email'])
        if existing:
            skipped += 1
            continue
        algorithm = detect_wp_hash_algorithm(wp_user['user_pass'])
        new_db.create_user({
            'username': wp_user['user_login'],
            'email': wp_user['user_email'],
            'password_hash': wp_user['user_pass'],
            'password_algorithm': algorithm,
            'display_name': wp_user['display_name'],
            'created_at': wp_user['user_registered'],
            'legacy_id': wp_user['ID'],
        })
        # Маппинг ролей: из wp_usermeta meta_key = 'wp_capabilities'
        roles = get_user_roles(wp_db, wp_user['ID'])
        new_db.assign_roles(wp_user['user_email'], roles)
        migrated += 1
    print(f"Migrated: {migrated}, Skipped: {skipped}")

Обработка входа и перехэширование

def login(email: str, password: str):
    user = db.get_user_by_email(email)
    if not user:
        return None
    if user.verify_password(password):
        if user.password_algorithm != 'bcrypt':
            user.upgrade_password_hash(password)
        return create_session(user)
    return None

Что входит в работу по миграции пользователей?

  • Аудит текущей базы пользователей и алгоритмов хэширования.
  • Разработка скриптов ETL с учётом маппинга ролей и дополнительных полей.
  • Реализация lazy migration (или принудительного сброса) с тестированием на копии.
  • Настройка мониторинга ошибок после деплоя (24-часовое наблюдение).
  • Документация по процедуре отката и резервное копирование.

Сроки выполнения и типичные ошибки

Ориентировочные сроки

  • Для базы до 100 000 пользователей: 2–3 рабочих дня на аудит, разработку и тестирование.
  • Для базы от 100 000 до 500 000: 5–7 дней с учётом ETL и нагрузочного тестирования.
  • В крупных проектах с десятками ролей и кастомными полями срок может быть увеличен.

Типичные ошибки при миграции

  • Пропуск проверки дубликатов по email — приводит к конфликтам и потере данных.
  • Игнорирование маппинга ролей — пользователь переносится, но теряет права доступа.
  • Попытка рехэшировать все пароли сразу — вызывает CPU-нагрузку и ошибки.
  • Отсутствие плана отката — при неудаче нет быстрого восстановления.
  • Незакрытие старых сессий — пользователи остаются в системе под старыми данными.

Советы:

  • Всегда тестируйте на копии базы.
  • Используйте транзакции и скрипты с rollback.
  • Настройте мониторинг ошибок после деплоя (первые 24 часа критичны).
  • Храните резервную копию старой базы и скрипт обратной миграции.

Сравнение алгоритмов хэширования

Алгоритм Длина хэша Устойчивость к брутфорсу Стандарт в CMS
bcrypt 60 символов Высокая (cost adjustable) Laravel, Symfony, Rails
phpass 34 символа Средняя (MD5-based) WordPress, Drupal 7
PBKDF2 98 символов Высокая Django, Python
MD5 32 символа Низкая Устаревшие системы

Закажите аудит вашего проекта. Свяжитесь с нами для консультации и получите точную смету с гарантией результата.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060