При администрировании и разработке в среде 1С:Предприятие нередко возникает ситуация, когда при создании нового пользователя информационной базы (особенно при использовании аутентификации средствами операционной системы) прикладной реквизит ИдентификаторПользователяИБ в справочнике пользователей не заполняется или принимает пустое значение вида 00000000-0000-0000-0000-000000000000. В результате пользователь успешно авторизуется в системе, но не видит доступных ему данных, так как механизмы прав и ограничения на уровне записей (RLS) привязаны к корректному уникальному идентификатору (GUID).
Разберем детально, почему возникает такая ошибка, как устроен механизм сопоставления пользователей и какими способами можно восстановить корректную работу базы данных.
Проанализируем основные технические причины, приводящие к обнулению идентификатора:
rmngr, rphost) кэшируют список пользователей информационной базы. Если кэш рабочих процессов рассинхронизирован, системные вызовы получения пользователя возвращают пустое значение или не могут сопоставить сеанс с объектом ПользовательИнформационнойБазы.ПользователиИнформационнойБазы хранится на системном уровне платформы, а справочник Пользователи — в таблицах базы данных. Платформа 1С не синхронизирует их автоматически на уровне движка, если в конфигурации не реализован соответствующий программный код в обработчиках событий или модуле сеанса.УникальныйИдентификатор генерируется только в момент выполнения метода Записать() объекта ПользовательИнформационнойБазы. Попытка прочитать идентификатор до этого момента возвращает пустой GUID.Если проблема проявилась внезапно после обновления релиза платформы 1С или изменения параметров кластера, самым быстрым и эффективным решением является полный перезапуск служб и очистка временных данных рабочих процессов.
Разберем по шагам порядок действий системного администратора:
MMC.services.msc) и остановим службу агента сервера 1С:Предприятия (1C:Enterprise 8.3 Server Agent / ragent).srvinfo / snccntx), не затрагивая конфигурационные файлы кластера (1Cv8.1CD и списки баз).Рассмотрим ситуацию, когда перезапуск сервера выполнен, но в прикладном справочнике уже накопились записи с нулевыми идентификаторами. Для разового восстановления связей между системными пользователями и элементами справочника используем внешнюю обработку или служебный код, выполняемый с административными правами.
Посмотрим на пример процедуры сопоставления:
УстановитьПривилегированныйРежим(Истина);
МассивПользователейИБ = ПользователиИнформационнойБазы.ПолучитьПользователей();
Для Каждого ПользовательИБ Из МассивПользователейИБ Цикл
// Выполняем поиск элемента справочника по имени пользователя
СсылкаНаПользователя = Справочники.Пользователи.НайтиПоНаименованию(ПользовательИБ.Имя);
Если ЗначениеЗаполнено(СсылкаНаПользователя) Тогда
ОбъектПользователь = СсылкаНаПользователя.ПолучитьОбъект();
// Проверяем, отличается ли идентификатор от текущего системного GUID
Если ОбъектПользователь.ИдентификаторПользователяИБ <> ПользовательИБ.УникальныйИдентификатор Тогда
ОбъектПользователь.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
ОбъектПользователь.Записать();
КонецЕсли;
КонецЕсли;
КонецЦикла;
Чтобы избежать подобных сбоев в самописных конфигурациях в будущем, настроим автоматическую проверку и заполнение реквизита ИдентификаторПользователяИБ в момент инициализации сеанса пользователя.
Разберем пример кода для процедуры УстановкаПараметровСеанса в модуле сеанса:
ТекущийИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ТекущийИБ <> Неопределено Тогда
УстановитьПривилегированныйРежим(Истина);
// Ищем запись в справочнике по аутентифицированному пользователю
ЭлементПользователя = Справочники.Пользователи.НайтиПоНаименованию(ТекущийИБ.Имя);
Если ЗначениеЗаполнено(ЭлементПользователя) Тогда
Если ЭлементПользователя.ИдентификаторПользователяИБ <> ТекущийИБ.УникальныйИдентификатор Тогда
ОбъектПользователя = ЭлементПользователя.ПолучитьОбъект();
ОбъектПользователя.ИдентификаторПользователяИБ = ТекущийИБ.УникальныйИдентификатор;
ОбъектПользователя.Записать();
КонецЕсли;
КонецЕсли;
КонецЕсли;
Важный момент: чтение системного списка пользователей через ПользователиИнформационнойБазы.ПолучитьПользователей() требует наличия административных прав. При выполнении кода от имени обычного пользователя обязательно используйте УстановитьПривилегированныйРежим(Истина), чтобы алгоритм не вызывал ошибку нарушения прав доступа.