B2BPRO.KZ | Рекламное агентство в Алматы

Как сделать личный кабинет клиента на WordPress без тяжёлых плагинов

Разработчица за монитором с макетом личного кабинета клиента, на переднем плане объёмное слово WordPress

Личный кабинет клиента на WordPress без тяжёлых плагинов собирается из четырёх частей: страница с формой входа, отдельная роль для клиентов, свои типы записей для документов и заказов и проверка прав на каждом запросе. Для небольшого кабинета с документами, статусами и перепиской это несколько сотен строк кода, и каждая строка работает только на вашу задачу.

Типичная ситуация выглядит так. Компании нужно, чтобы клиент заходил на сайт, видел свои договоры, счета и статус проекта, а не писал каждый раз менеджеру. Разработчик ставит комбайн для «членства и личных кабинетов», и сайт получает три десятка таблиц, десяток фоновых задач и обновления, которые надо отслеживать. На проектах B2BPRO.KZ мы чаще всего видим, что из возможностей комбайна клиенту нужно процентов пять. Ниже разберём, как закрыть эти пять процентов собственным кодом и где всё же лучше взять готовое.

Когда личный кабинет можно собрать без большого плагина

Собственный кабинет оправдан, когда набор функций небольшой и понятный: вход, список документов, статусы, форма обращения. Если же нужны платные подписки, закрытые курсы с прогрессом, сложные роли и интеграция с несколькими платёжными системами, разумнее брать готовое решение и донастраивать его.

Личный кабинет клиента — это защищённая часть сайта, где авторизованный пользователь видит только свои данные и может выполнять разрешённые действия: скачивать документы, отправлять заявки, смотреть историю заказов. Ключевое слово здесь «только свои». Вся архитектура строится вокруг одного правила: на каждом запросе сервер сам определяет, кто пользователь и что ему можно видеть.

Ориентиры для выбора мы собрали в таблице. Это практические наблюдения, а не цифры из документации, и точные пороги зависят от проекта.

Задача Свой код Готовый плагин
Вход, список документов, статусы заказов Подходит, объём небольшой Избыточно
Форма обращения с вложением и историей Подходит при аккуратной проверке файлов Допустимо, если уже стоит нужный плагин форм
Платные подписки и автоплатежи Не рекомендуем, много юридических и платёжных деталей Лучше готовое решение
Интернет-магазин с историей заказов Не нужно, кабинет уже есть в магазинных решениях Используйте встроенный кабинет
Закрытые курсы с прогрессом Трудоёмко Лучше готовое решение

Как устроена страница входа без плагина

Форму входа можно вывести на любой странице одной функцией: wp_login_form(). Согласно документации WordPress по wp_login_form, она по умолчанию сразу выводит HTML, а при параметре echo со значением false возвращает его строкой. Адрес для перенаправления после входа задаётся параметром redirect и должен быть абсолютным.

Для шорткода используйте именно возврат строки, иначе форма окажется не там, где стоит шорткод. Минимальный пример (иллюстрация, адаптируйте под свою тему):

function b2b_login_form() {
    if ( is_user_logged_in() ) {
        return '';
    }
    return wp_login_form( array(
        'echo'     => false,
        'redirect' => home_url( '/kabinet/' ),
    ) );
}
add_shortcode( 'b2b_login', 'b2b_login_form' );

Поставьте шорткод на страницу «Вход», а на страницу «Кабинет» добавьте проверку: если пользователь не авторизован, показывайте приглашение войти вместо данных. Не опирайтесь на то, что страницу «никто не знает». Скрытая ссылка не защита, защитой служит только проверка на сервере.

Что делать со стандартной страницей wp-login.php

Стандартную страницу входа можно оставить для сотрудников, а клиентов вести через свою страницу. Это решение ради удобства: скрытие адреса никак не заменяет надёжных паролей и ограничения попыток входа. Если вы всё же меняете адрес входа, сначала проверьте, что у сотрудников и у служебных интеграций остаётся рабочий путь.

Как завести отдельную роль для клиентов

Отдельная роль нужна, чтобы клиенты не получали лишних прав и чтобы администратор мог одним взглядом отличить их от сотрудников. Роль создаёт функция add_role(). По справочнику WordPress по add_role, она добавляет роль, если её ещё нет, и возвращает объект роли, а для уже существующей роли возвращает null. Возможности передаются массивом, и значение false явно запрещает возможность.

Вызывайте add_role() один раз при активации плагина или темы, а не на каждой загрузке страницы. Для проекта, где логика лежит в небольшом собственном плагине, это стандартная практика. Если позже нужно изменить возможности уже созданной роли, одного повторного вызова недостаточно: пользователи в обсуждениях справочника советуют сначала удалить роль через remove_role(), затем создать заново.

register_activation_hook( __FILE__, function () {
    add_role( 'b2b_client', 'Клиент', array( 'read' => true ) );
} );

Минимальный набор возможностей для клиента — только чтение. Всё остальное, например доступ к админке, должно быть закрыто. Скрытую от клиентов админ-панель стоит дополнительно проверить на практике: войдите тестовым клиентом и убедитесь, что адрес /wp-admin/ не открывает лишнего.

Как хранить документы, заказы и статусы

Для каждой сущности кабинета заведите собственный тип записи и привязывайте её к клиенту. Самый простой способ: автор записи и есть клиент. Тогда запрос «покажи документы этого клиента» превращается в выборку записей нужного типа с параметром автора. Договоры, счета и акты — один тип записи с метаполем «вид документа», заказы — другой.

Такая схема удобна менеджерам: они создают документ в обычной админке, выбирают клиента автором и прикладывают файл. Для клиента запись видна только в кабинете. Сами записи лучше сделать непубличными, чтобы они не попали в карту сайта и поиск. Параметр публичности задаётся при регистрации типа записи, а страницу с выводом отдаёт ваш шорткод.

$docs = new WP_Query( array(
    'post_type'      => 'b2b_document',
    'author'         => get_current_user_id(),
    'posts_per_page' => 50,
) );

Обратите внимание на строку с автором: идентификатор берётся из текущей сессии, а не из адреса или формы. Если брать его из параметра в ссылке, один клиент сможет открыть чужие документы, просто подставив другое число. Это самая частая ошибка самодельных кабинетов.

Как отдавать файлы документов

Файлы договоров нельзя хранить в обычной папке загрузок, если адрес можно угадать. Надёжнее положить их в закрытую папку вне публичного доступа и отдавать через PHP после проверки: пользователь вошёл, файл принадлежит ему. Для небольших файлов этого достаточно. Для крупных потребуется отдавать их потоком и следить за лимитами хостинга.

Как сделать красивые адреса внутри кабинета

Адреса вида /kabinet/dokumenty/ и /kabinet/zakazy/ удобнее параметров в строке. Их можно получить через endpoints. Функция add_rewrite_endpoint(), как описано в справочнике WordPress, добавляет endpoint вроде /trackback/ и создаёт query var с тем же именем. Места применения задаются битовой маской констант EP_*, например EP_PAGES для страниц.

Обработать значение удобно в хуке template_redirect: там вы читаете query var и решаете, какой раздел показывать. После регистрации endpoint нужно один раз сбросить правила перезаписи через flush_rewrite_rules(). Справочник рекомендует делать это при активации и деактивации плагина, а не на каждой загрузке. Сброс правил на каждом запросе заметно замедляет сайт.

add_action( 'init', function () {
    add_rewrite_endpoint( 'dokumenty', EP_PAGES );
    add_rewrite_endpoint( 'zakazy', EP_PAGES );
} );

Если разделов много, соберите их в один шаблон с меню слева. Для клиента кабинет должен выглядеть как продолжение сайта, а не как отдельный сервис.

Как защитить формы кабинета

Любая форма в кабинете (обращение, смена данных, загрузка файла) должна проверять три вещи: что пользователь вошёл, что у него есть право на действие и что запрос не подделан. Для третьей проверки в WordPress есть nonce. Согласно разделу о nonce в руководстве разработчика WordPress, это токен, защищающий URL и формы от подделки запросов. Он действует примерно сутки: фактически от 12 до 24 часов, потому что считается двумя интервалами по 12 часов.

Важный нюанс: nonce не отвечает за права доступа. В документации прямо сказано, что на него нельзя полагаться для аутентификации, авторизации и контроля доступа, для этого используют current_user_can(). Кроме того, nonce не одноразовый, поэтому от повторной отправки одного и того же запроса он не защищает. Для гостей WordPress формирует одинаковый nonce, и это ещё одна причина не принимать никаких решений о правах на его основе.

Рабочий порядок для формы такой: вывести скрытое поле через wp_nonce_field(), при отправке проверить его через wp_verify_nonce(), затем проверить права и только потом выполнять действие. Данные из формы очищайте при сохранении и экранируйте при выводе. Это рутина, но именно на ней ломается большинство самописных решений.

Загрузка файлов клиентами

Если клиент может прикладывать файлы, ограничьте список разрешённых типов и размер, а имена файлов приводите к безопасному виду. Исполняемые файлы и скрипты не принимайте вообще. Это общая рекомендация по безопасности, а не требование какой-то одной функции WordPress, и точные пороги вы определяете сами исходя из хостинга.

Как закрыть кабинет от поисковиков и кэша

Страницы кабинета не должны попадать в поиск: добавьте на них директиву запрета индексации и не включайте в карту сайта. Отдельно проверьте кэширование. Если на сервере включено кэширование страниц целиком, закрытая страница, которую увидел один клиент, не должна отдаваться из кэша другому. Исключите адреса кабинета из страничного кэша в настройках кэширующего плагина или сервера. Это легко проверить: войдите двумя разными тестовыми клиентами в разных браузерах и сравните содержимое.

Для сайтов в Казахстане есть ещё одно соображение. Кабинет почти всегда хранит персональные данные клиентов: ФИО, контакты, реквизиты. Требования законодательства о персональных данных и их хранении имеет смысл сверить с юристом до запуска, а техническую часть (резервные копии, доступы сотрудников, журнал действий) заложить в проект сразу.

Какие ошибки чаще всего встречаются в самодельных кабинетах

Ошибки в таких проектах повторяются от сайта к сайту. Ниже перечень того, что мы чаще всего находим при аудите чужих кабинетов. Это практические наблюдения, а не статистика.

Ошибка К чему приводит Как исправить
Идентификатор клиента берётся из ссылки или формы Клиент видит чужие документы, подставив другое число Брать идентификатор из текущей сессии
Файлы лежат в открытой папке с предсказуемыми именами Документы открываются по прямой ссылке без входа Хранить в закрытой папке и отдавать после проверки
Права проверяются только скрытием кнопок Запрос можно отправить в обход интерфейса Проверять права на сервере при каждом действии
Кабинет попадает в страничный кэш Один клиент видит страницу другого Исключить адреса кабинета из кэша
Клиентская роль получает лишние возможности Доступ к админке или чужим записям Оставить роли только чтение и проверить вход тестовым клиентом

Все эти пункты проверяются за час и без специальных инструментов. Поэтому чек-лист ниже стоит пройти до запуска, а не после первой жалобы клиента.

Как проверить кабинет перед запуском

Перед запуском пройдите короткий чек-лист. Он занимает час и закрывает самые дорогие ошибки.

  1. Создайте двух тестовых клиентов и добавьте каждому по несколько документов.
  2. Войдите первым клиентом и попробуйте открыть документ второго по прямой ссылке. Должен быть отказ.
  3. Проверьте, что гость, открывший адрес кабинета, видит приглашение войти, а не данные.
  4. Попробуйте отправить форму без nonce или с чужим. Запрос должен отклоняться.
  5. Убедитесь, что клиент не попадает в админку.
  6. Проверьте, что страницы кабинета не отдаются из кэша разным пользователям.
  7. Проверьте письма: восстановление пароля должно приходить и вести на понятную страницу.

Восстановление пароля стоит упомянуть отдельно. Клиенты забывают пароли чаще, чем кажется, и письмо, которое уходит в спам, превращается в звонок менеджеру. Проверьте отправку писем с вашего домена и при необходимости настройте почтовую отправку через SMTP.

Пример: кабинет для сервисной компании

Рассмотрим вымышленный пример, чтобы увидеть, как части складываются в целое. Сервисная компания обслуживает оборудование клиентов по договорам. Клиенту нужно видеть договор, акты выполненных работ, график визитов инженера и отправлять заявку на выезд.

Для такого кабинета достаточно роли «Клиент», трёх типов записей (договоры, акты, заявки) и двух страниц: список документов и форма заявки. Менеджер заводит документ в админке и выбирает клиента автором. Заявка из кабинета создаёт запись нужного типа и отправляет письмо ответственному сотруднику. Статус заявки сотрудник меняет в админке, и клиент видит его при следующем входе. Никакой сложной интеграции, никаких подписок, и весь код укладывается в один небольшой плагин.

Если позже понадобится выгружать заявки в CRM, это решается отдельной доработкой: записи уже лежат в структурированном виде, и подключить обмен проще, чем разбирать данные из чужого плагина.

Какие письма и уведомления нужны клиенту

Кабинет без уведомлений превращается в место, куда клиент заходит раз в месяц. Минимальный набор писем: подтверждение получения заявки, смена её статуса, появление нового документа и восстановление пароля. Письма отправляет стандартная функция WordPress wp_mail(), а надёжность доставки обеспечивает настройка SMTP.

Следите за тоном: письмо должно коротко говорить, что произошло, и вести в нужный раздел кабинета. Не отправляйте в письме сами документы с персональными данными, лучше дайте ссылку на вход. Так вы не потеряете контроль над тем, кто и когда видел файл.

Как поддерживать кабинет после запуска

После запуска кабинет требует той же заботы, что и любой рабочий сервис. Регулярно обновляйте ядро WordPress, тему и подключённые плагины, делайте резервные копии базы и папки с файлами документов и проверяйте, что копию действительно можно развернуть. Раз в квартал просматривайте список пользователей: сотрудники уходят, клиенты закрывают договоры, и лишние аккаунты с доступом не нужны.

Отдельно заведите привычку проверять чек-лист из предыдущего раздела после каждого крупного обновления. Любое изменение темы или кэша может незаметно открыть то, что было закрыто. Если у вас нет ресурса следить за этим внутри компании, поддержку проекта разумнее отдать исполнителю по договору.

Когда собственный кабинет лучше доверить разработчику

Самостоятельно собрать простой кабинет под силу тому, кто уверенно пишет на PHP и понимает безопасность WordPress. Если кабинет должен интегрироваться с учётной системой или CRM, показывать данные из внешних источников, поддерживать роли сотрудников клиента или выдерживать нагрузку, лучше сразу привлечь команду. Цена ошибки в таком проекте высока: утечка чужих документов бьёт по репутации сильнее, чем лишний месяц разработки. Подробнее о наших подходах можно прочитать на странице разработка сайтов под ключ. B2BPRO.KZ разрабатывает сайты и кабинеты на WordPress для компаний в Казахстане и сопровождает их после запуска.

Если кабинет уже есть и вы сомневаетесь в его защите, начните с чек-листа выше. Он быстро показывает, где в проекте дыры, и по его результатам можно решить, чинить текущую версию или переписывать.

Частые вопросы

Можно ли сделать личный кабинет на WordPress совсем без плагинов?

Да, для простого кабинета достаточно собственного кода: форма входа через wp_login_form, отдельная роль, свои типы записей и проверка прав. Обычно такой код оформляют небольшим собственным плагином, чтобы он не терялся при смене темы. Для платных подписок и сложных ролей разумнее использовать готовые решения.

Как защитить документы клиентов от доступа посторонних?

Храните файлы в закрытой папке и отдавайте их через PHP только после проверки, что пользователь вошёл и файл принадлежит ему. Идентификатор клиента берите из текущей сессии, а не из параметров в ссылке. Перед запуском проверьте доступ вторым тестовым клиентом по прямой ссылке.

Нужен ли nonce, если у пользователя уже есть права?

Да, nonce защищает от подделки запросов, а права проверяются отдельно. Согласно руководству разработчика WordPress, nonce нельзя использовать вместо проверки прав. Нужны обе проверки: nonce для защиты запроса и функция current_user_can для контроля доступа.

Как сделать адреса вида /kabinet/dokumenty/ на WordPress?

Используйте функцию add_rewrite_endpoint, которая добавляет endpoint и одноимённую query var. Значение читайте в хуке template_redirect. После регистрации один раз сбросьте правила перезаписи, например при активации плагина, а не на каждой загрузке страницы.

Сколько времени занимает разработка простого кабинета?

Это зависит от набора функций, поэтому единой цифры нет. Обычно работа складывается из четырёх этапов: уточнение задач, макеты, разработка и тестирование с проверкой безопасности. Чем меньше интеграций и ролей, тем быстрее запуск. Сроки лучше называть после разбора конкретной задачи.

Нужно ли закрывать кабинет от индексации?

Да, страницы с личными данными не должны попадать в поиск и в карту сайта. Кроме того, исключите их из страничного кэша, чтобы данные одного клиента не показывались другому. Проверить это можно двумя тестовыми аккаунтами в разных браузерах.

Прокрутить вверх