Свои страницы личного кабинета - раздел, меню, права, данные
Добавляем в личный кабинет свои разделы: страницы и меню, закрытие от гостей, возврат после входа и вывод данных покупателя.
Что нужно знать заранее
Личный кабинет - это обычный раздел сайта с обычными страницами. Отдельного модуля кабинета нет, а штатные страницы заказов и профиля собраны из компонентов на таких же страницах.
Закрывать кабинет нужно на уровне раздела, а не каждой страницы отдельно. Забытая страница в закрытом разделе - типовая утечка: адрес угадывается, а данные показываются любому посетителю.
Данные всегда берут по текущему пользователю. Идентификатор из адреса страницы принимать нельзя: подставив чужой номер, посетитель увидит чужие документы.
Шаги
- Завести раздел кабинета и положить в него свои страницы обычным способом.
- Закрыть весь раздел от неавторизованных одной проверкой на уровне раздела.
- Собрать меню раздела и добавить в него свои пункты рядом со штатными.
- Выводить данные строго по текущему пользователю, без идентификатора из адреса.
- Проверить возврат на нужную страницу после входа и поведение кэша страниц.
Решение
Закрываем раздел от неавторизованных:
// /personal/.section.php или подключаемый файл разделаif (!$USER->IsAuthorized()) { LocalRedirect('/auth/?backurl=' . urlencode($APPLICATION->GetCurPageParam()));}// проверка на уровне раздела закрывает и будущие страницы тожеПроверка на уровне раздела надёжнее проверки в каждой странице. Новая страница внутри раздела закрывается автоматически, и никто не забывает вставить в неё пару строк защиты.
Добавляем свои пункты в меню кабинета:
// /personal/.left.menu.php - обычный файл меню раздела$aMenuLinks = [ ['Мои заказы', '/personal/order/', [], [], ''], ['Мои документы', '/personal/docs/', [], [], ''], // свой раздел кабинета ['Бонусный счёт', '/personal/bonus/', [], [], ''],];// условие показа пункта задают пятым элементом массива, обычным выражениемМеню кабинета ничем не отличается от меню любого раздела. Свои пункты добавляют в тот же файл, а порядок и вложенность задают так же, как в остальных разделах сайта.
Выводим данные текущего покупателя:
global $USER;$rows = \Vendor\Module\DocumentTable::getList([ 'filter' => ['=USER_ID' => (int)$USER->GetID()], // только свои записи 'order' => ['DATE_CREATE' => 'DESC'],])->fetchAll();Отбор по текущему пользователю - обязательная часть любой страницы кабинета. Идентификатор из адреса или из формы для этого не годится: он подделывается за секунду и открывает чужие данные.
Возвращаем посетителя на нужную страницу после входа:
$APPLICATION->IncludeComponent('bitrix:system.auth.form', '', [ 'REGISTER_URL' => '/auth/registration/', 'FORGOT_PASSWORD_URL' => '/auth/forgot-password/',]);// адрес возврата приходит параметром запроса и подставляется формой автоматическиВозврат после входа экономит посетителю лишний переход. Без него человек с письма попадает на главную и заново ищет нужную страницу кабинета руками.
Отключаем кэш страниц кабинета:
// в шаблоне страницы кабинетаdefine('BX_SECURITY_SHOW_MESSAGE', true);$APPLICATION->SetPageProperty('composite_frame_mode', 'no');// личные данные не должны попадать в кэш готовых страницТипичные проблемы
Страница кабинета открывается без авторизации.
Проверка стоит на отдельных страницах, а не на всём разделе целиком. Защиту ставят на уровне раздела, тогда новые страницы закрыты сразу.
Посетитель видит чужие документы.
Записи отбираются по идентификатору из адреса страницы. Отбор всегда делают по текущему пользователю, а параметр адреса игнорируют.
После входа человек попадает на главную.
Форме авторизации не передан адрес возврата. Его подставляют в параметр запроса при переходе на страницу входа.
В кабинете показываются данные другого покупателя.
Страница попала в кэш готовых страниц и отдаётся всем одинаковой. Страницы с личными данными исключают из такого кэша.
Свой пункт меню не появился в кабинете.
Пункт добавлен в меню другого раздела или в файл меню другого типа. Правят тот файл меню, который читает компонент на странице кабинета.
Частые вопросы
Нужен ли отдельный модуль под кабинет?
Нет, кабинет собирается из обычных страниц и компонентов. Свой модуль нужен только под собственные данные и их хранение.
Как закрыть раздел не только от гостей?
Проверять группу пользователя или права на данные в том же месте, где стоит проверка авторизации. Права на файлы дополняют такую проверку на уровне сервера.
Можно ли вынести кабинет на поддомен?
Можно, но тогда придётся решать вопрос общей авторизации между доменами. На одном домене кабинет заметно проще в поддержке.
Что делать с кэшем на страницах кабинета?
Кэшировать только неизменные части и исключать страницу из кэша готовых страниц. Личные данные в общий кэш попадать не должны.
Как показать в кабинете данные из внешней системы?
Забирать их по идентификатору текущего пользователя и кэшировать на минуты. Прямой запрос к чужой системе на каждый заход делает кабинет медленным.
Смежное
- Заказы и статусы - оглавление подтемы
- Личный кабинет покупателя: список заказов, повтор и отмена - штатные страницы кабинета
- Страница и форма авторизации: компоненты, шаблоны, возврат после входа - вход и возврат подробнее
- Права на файлы и папки: файловая система и права структуры - закрытие раздела на уровне сервера
- Дилерский доступ: свои цены, свой каталог, документы - кабинет для оптового покупателя
- Композитный сайт: включение, динамические области, сброс - почему личные страницы исключают из кэша
- Личный кабинет покупателя - устройство штатного кабинета