Как в 1С ограничить доступ к документу, чтобы его мог видеть и открывать только автор?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе разработки и администрирования баз данных «1С:Предприятие» часто возникает задача конфиденциальности. Бизнес требует, чтобы определенные документы (например, аудит, личные продажи, кадровые приказы или черновики) после проведения или записи были доступны для просмотра и редактирования только их непосредственному автору (создателю). Другие пользователи системы не должны иметь к ним доступа.

В этой статье мы подробно разберем, как решить эту задачу на платформе «1С:Предприятие 8» (8.2 и 8.3), рассмотрим ошибки, с которыми сталкиваются начинающие разработчики, и проанализируем различные методы реализации — от простых проверок в форме до надежного ограничения на уровне базы данных (RLS).

Способ 1. Ограничение доступа на уровне формы (быстрое, но компромиссное решение)

Самый простой вариант, который первым приходит в голову начинающим разработчикам — поставить проверку при открытии формы документа. Если текущий пользователь системы не совпадает с реквизитом Автор, то мы просто запрещаем открытие формы.

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

Для обычного приложения (Обычные формы):

В обычных формах проверка выполняется в обработчике события ПередОткрытием формы документа. Нам необходимо использовать параметр Отказ.


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    
    // Проверяем, что документ уже существует в базе (не новый)
    Если ЗначениеЗаполнено(Ссылка) Тогда
        
        // Сравниваем автора документа с текущим пользователем из параметров сеанса
        Если ЭтотОбъект.Автор <> ПараметрыСеанса.ТекущийПользователь Тогда
            Предупреждение("У вас нет прав на просмотр данного документа! Документ доступен только его автору.");
            Отказ = Истина;
            Возврат;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Для управляемого приложения (Управляемые формы):

В управляемом приложении обращение к параметрам сеанса напрямую с клиента невозможно, поэтому мы должны делегировать проверку серверному контексту.


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
        Если Не ДокументДоступенТекущемуПользователю(Объект.Ссылка) Тогда
            ПоказатьПредупреждение(, "Доступ ограничен! Вы не являетесь автором этого документа.");
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ДокументДоступенТекущемуПользователю(СсылкаНаДокумент)
    
    // Получаем автора напрямую из базы данных и сравниваем с параметром сеанса
    АвтораДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаДокумент, "Автор");
    Возврат (АвтораДокумента = ПараметрыСеанса.ТекущийПользователь);
    
КонецФункции

Способ 2. Исправление ошибки неинициализированного параметра сеанса

Часто при переносе или написании этого кода разработчики сталкиваются с системной ошибкой: «Попытка получения неинициализированного значения параметра сеанса (ТекущийПользователь)». Выясним причину ее возникновения.

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

Для решения этой проблемы нам необходимо открыть Модуль сеанса и прописать инициализацию в предопределенной процедуре УстановкаПараметровСеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    // Проверяем, нужно ли инициализировать конкретный параметр
    Если ТребуемыеПараметры = Неопределено 
        Или ТребуемыеПараметры.Найти("ТекущийПользователь") <> Неопределено Тогда
        
        // Находим пользователя ИБ и ищем его соответствие в справочнике "Пользователи"
        ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
        НайденныйПользователь = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ", ТекущийПользовательИБ.УникальныйИдентификатор);
        
        Если ЗначениеЗаполнено(НайденныйПользователь) Тогда
            ПараметрыСеанса.ТекущийПользователь = НайденныйПользователь;
        Иначе
            // Альтернативный поиск по имени, если идентификаторы не сопоставлены
            НайденныйПользователь = Справочники.Пользователи.НайтиПоНаименованию(ТекущийПользовательИБ.Имя);
            ПараметрыСеанса.ТекущийПользователь = НайденныйПользователь;
        EndIf;
        
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Решение проблемы несовпадения типов данных (Сотрудники vs Пользователи)

Еще одна неочевидная проблема, с которой часто сталкиваются в нетиповых или сильно измененных конфигурациях: реквизит Автор в документе имеет тип СправочникСсылка.Сотрудники, а параметр сеанса ТекущийПользователь — это тип СправочникСсылка.Пользователи.

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


&НаСервереБезКонтекста
Функция ДокументДоступенСотруднику(СсылкаНаДокумент)
    
    АвторДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаДокумент, "Автор");
    ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь;
    
    // Ищем сотрудника, связанного с текущим пользователем системы
    СотрудникПользователя = Справочники.Сотрудники.НайтиПоРеквизиту("ФизическоеЛицо", ТекущийПользователь.ФизическоеЛицо);
    
    Возврат (АвторДокумента = СотрудникПользователя);
    
КонецФункции

Почему ограничение через форму НЕ является безопасным?

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

  1. Отображение данных в списках: Другие пользователи все равно увидят закрытый документ в журналах и списках. Им будут видны дата, номер, контрагент, сумма и другие реквизиты, выведенные на форму списка.
  2. Доступ через отчеты: Любой пользователь сможет увидеть все закрытые данные в универсальных отчетах, отчетах по регистрам накопления или через консоль запросов.
  3. Программный доступ: Сведения из документа легко прочитать сторонними обработками выгрузки данных.

Способ 4. Фильтрация списков и журналов документов (настройка интерфейса)

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Устанавливаем жесткий отбор в динамическом списке
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Автор");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.Использование = Истина;
    
    // Блокируем для пользователя возможность отключить этот отбор в настройках формы
    ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
    ЭлементОтбора.ПравоеЗначение = ПараметрыСеанса.ТекущийПользователь;
    
КонецПроцедуры

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

Способ 5. Ограничение доступа на уровне записей (RLS) — максимально надежная защита

Если безопасность данных является приоритетной задачей предприятия, единственным правильным решением будет использование встроенного механизма платформы RLS (Row-Level Security).

Механизм RLS работает на уровне СУБД (SQL-сервера). Платформа автоматически модифицирует любой запрос пользователя к таблице документов, отсекая записи, к которым у пользователя нет прав доступа. Ни через отчеты, ни через программный код, ни через консоль запросов обойти RLS невозможно.

Пошаговая настройка RLS для ограничения по автору:

  1. Откройте конфигуратор, перейдите на вкладку Роли и выберите роль, назначенную вашим пользователям (например, "Менеджер" или специально созданную роль "ДоступТолькоКСвоимДокументам").
  2. Найдите в списке объектов нужный документ и перейдите на вкладку Права.
  3. Выберите право Чтение (а также при необходимости "Изменение" и "Удаление").
  4. В нижнем окне "Ограничение доступа к данным" добавьте новое ограничение для поля <Прочие поля>.
  5. Напишите следующий шаблон SQL-запроса ограничения:

ГДЕ Автор = &ПараметрыСеанса.ТекущийПользователь

Важные особенности использования RLS:

Рекомендация: Автоматическое заполнение реквизита «Автор»

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

Разберем, как правильно заполнять автора на уровне Модуля объекта в обработчике события ПередЗаписью:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем, что документ не записывается в режиме обмена данными
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    // Заполняем автора только один раз — при первом сохранении нового документа
    Если ЭтоНовый() Тогда
        Если ЗначениеЗаполнено(ПараметрыСеанса.ТекущийПользователь) Тогда
            ЭтотОбъект.Автор = ПараметрыСеанса.ТекущийПользователь;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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

← На главную