При развертывании систем на платформе 1С:Предприятие 8.3 часто возникает задача ограничения количества активных сеансов для одного пользователя. Это может быть продиктовано как требованиями безопасности, так и необходимостью контроля за потреблением клиентских лицензий. Однако стандартные методы, которые отлично работают в локальной сети или через RDP, могут давать сбой при использовании тонкого клиента через веб-сервер (HTTP/HTTPS). Разберем подробно, почему это происходит и как реализовать надежную защиту от повторных подключений.
Когда пользователь подключается к информационной базе через веб-сервер, взаимодействие происходит по протоколу HTTP. В отличие от прямого TCP-соединения, протокол HTTP является "протоколом без сохранения состояния". Это вносит свои коррективы в механизмы работы платформы:
Sleep) и будет ожидать таймаута, установленного в настройках веб-сервера (обычно 20 минут).Прежде чем приступать к написанию кода, выясним причину, по которой отладка кажется невозможной. Для того чтобы отладчик "увидел" ваш сеанс через веб-сервер, необходимо выполнить следующие действия:
default.vrd убедитесь, что параметр debug="true" включен.После этого процедура ПередНачаломРаботыСистемы станет доступна для анализа, и мы сможем проверить логику поиска дублирующих входов.
Рассмотрим основной способ решения задачи средствами встроенного языка. Нам потребуется функция ПолучитьСеансыИнформационнойБазы(). Она возвращает массив всех активных сеансов. Проанализируем пример кода, который нужно разместить в Модуле управляемого приложения:
Процедура ПередНачаломРаботыСистемы(Отказ)
// Получаем текущего пользователя
ТекущийПользовательСистемы = ПользователиИнформационнойБазы.ТекущийПользователь();
ИмяПользователя = ТекущийПользовательСистемы.Имя;
УникальныйИдентификаторПользователя = ТекущийПользовательСистемы.УникальныйИдентификатор;
// Получаем список всех активных сеансов
ВсеСеансы = ПолучитьСеансыИнформационнойБазы();
КоличествоСеансов = 0;
Для Каждого Сеанс Из ВсеСеансы Цикл
// Проверяем соответствие пользователя по УИН (Уникальному Идентификатору)
Если Сеанс.Пользователь.УникальныйИдентификатор = УникальныйИдентификаторПользователя Тогда
КоличествоСеансов = КоличествоСеансов + 1;
КонецЕсли;
КонецЦикла;
// Если это не первый сеанс данного пользователя - блокируем вход
// Важно: текущий сеанс уже считается в массиве, поэтому проверяем > 1
Если КоличествоСеансов > 1 Тогда
Сообщить("Внимание! Под данным пользователем уже выполнен вход в систему.
|Одновременная работа нескольких сеансов запрещена политикой безопасности.");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Важное замечание: Метод ПолучитьСеансыИнформационнойБазы() требует наличия прав администратора у пользователя. Если ваши пользователи работают с ограниченными правами, этот код вызовет ошибку доступа. В таком случае проверку нужно выносить в привилегированный модуль на стороне сервера.
Как мы выяснили ранее, при работе через веб-сервер сеансы часто "повисают". Если мы будем просто запрещать вход, пользователь, у которого случайно закрылся браузер, не сможет войти в систему следующие 20 минут. Разберем, как усовершенствовать алгоритм, чтобы он автоматически закрывал старые сеансы.
Вместо установки Отказ = Истина, мы можем программно завершить предыдущий сеанс. Для этого используется метод ЗавершитьСеанс().
// Фрагмент кода для завершения старого сеанса
Для Каждого Сеанс Из ВсеСеансы Цикл
Если Сеанс.Пользователь.УникальныйИдентификатор = УникальныйИдентификаторПользователя
И Сеанс.НомерСеанса <> НомерТекущегоСеанса() Тогда
Попытка
// Завершаем "чужой" сеанс того же пользователя
ЗавершитьСеанс(Сеанс);
ЗаписьЖурналаРегистрации("Доступ", УровеньЖурналаРегистрации.Предупреждение, , ,
"Завершен предыдущий сеанс пользователя: " + ИмяПользователя);
Исключение
// Обработка ошибки, если не хватает прав на завершение
КонецПопытки;
КонецЕсли;
КонецЦикла;
Проанализируем этот подход: он гораздо лояльнее к пользователю. Система видит, что человек пытается войти снова, и "выталкивает" его старую, возможно зависшую, сессию. Это исключает звонки в техподдержку с просьбой "сбросить сеанс".
Если вы используете именно Тонкий клиент (а не браузер), можно применить административный метод контроля на стороне операционной системы. Это полезно, когда нужно запретить запуск именно нескольких экземпляров программы на одном компьютере.
Рассмотрим пример .cmd файла, который проверяет, запущен ли процесс 1cv8c.exe или 1cv8s.exe перед стартом:
@echo off
SET SEARCH_EXE=1cv8c.exe
tasklist /fi "imagename eq %SEARCH_EXE%" /fo table /nh | find /c /i "%SEARCH_EXE%" > nul
if %ERRORLEVEL%==0 (
echo Программа 1С уже запущена на этом компьютере!
pause
) else (
start "" "C:\Program Files\1cv8\common\1cestart.exe"
)
Однако помните, что этот метод имеет существенные недостатки: он не защищает от входа с другого компьютера или через веб-браузер. Поэтому программный метод внутри 1С остается приоритетным.
Подведем итоги нашего исследования. Для реализации надежного запрета повторных подключений через веб-сервер следует придерживаться следующей стратегии:
УникальныйИдентификаторПользователя остается константным для объекта метаданных.ВремяПоследнейАктивности), если решите оставить проверку без автозавершения.УстановитьПривилегированныйРежим(Истина)), чтобы избежать ошибок прав доступа у обычных пользователей.default.vrd установите разумное время жизни неактивного сеанса (sessionMaxAge), чтобы уменьшить количество "спящих" сессий в списке.Применяя данные подходы, вы создадите стабильный механизм управления сессиями, который будет корректно работать даже в условиях нестабильного интернет-соединения при работе через веб-интерфейс.