RLS – Record Level Security
Это чтобы выпендриться...
С определенной версии БСП разделяют на 2 варианта работы ограничением доступа на уровне записей:
- Стандартный (использовался ранее)
- Производительный
Стандартный
Ограничения устанавливаются на операции с данными: Чтение, Добавление, Изменение и Удаление. На основные операции накладывать нет смысла, так как они являются частными случаями вышеперечисленных.
В таблице ограничения доступа данных есть 2 колонки:
- Поля - Если указаны отдельные поля, то ограничения действуют только при получении данных с этими полями, т.е. в этом случае надо исключит из запроса указанные поля и запрос вернет все записи. Если стоит "Прочие поля", то ограничение действует всегда
- Ограничение доступа - это условие, которое добавляется к запросу. Его можно написать с помощью конструктора запросов.
Следует отметить, что при наложении условий на конкретные поля можно вывести полные список без указания этих полей (например запросом или изменить колонки в форме списка), но открыть форму объекта с неразрешенными данными нельзя, так как при открытии формы загружается полный контекст основного реквизита "объект", т.е. со всеми полями.
Ограничения можно установит на запись целиком или на конкретные поля записи.
Для установки ограничения на запись целиком используется специальное поле "Прочие поля".
Важно, что для операций изменения, добавления и удаления можно задать только одно условие, а для операции чтения можно задать несколько ограничений доступа на уровне записей.
Например:

В этом случае поля Ссылка, Номер, Дата, ВерсияДанных могут читать все пользователи, а остальные поля только по условию ограничения. Это поможет в том случае, если при обработке одного объекта (например документа) надо обратиться к данным другого объекта (например определить наличие связанного), не зависимо от того, есть у пользователя права или нет.
Неявное чтение некоторых полей так же выполняется в процессе создания объектов. Например, если установлена автонумерация, то при создании объекта происходит неявное чтение поля Код.
Если справочник подчиненный, то происходит обращение к полю Владелец. Если справочник иерархический, тогда происходит обращение к полю Родитель. Если у бизнес-процесса или задачи установлен режим автоматического определения времени, то при записи будет выполнятся чтение полей Дата и Ссылка.
Исключить появление ошибки при обращении к запрещенным данным можно также используя в запросах команду "Разрешенные" (динамические списки используют эту команду по умолчанию).
При установке прав доступа к регистрам надо установит права не только к праву "Чтение", но и к праву "Просмотр", иначе пользователь не сможет формировать отчет по регистру.
Ограничение добавляется при обращении к данным, т.е. к запросу получения данных добавляются условия из ограничения.
Язык ограничений является подмножеством языка запросов. В запросе ограничения доступа к данным всегда присутствует одна таблица в качестве источника данных ‑ это таблица объекта, на который накладывается ограничение (основной объект ограничения).
Особенности языка ограничений:
- В запросе всегда присутствует одна таблица в качестве источника данных – это таблица объекта, на который накладывается ограничение
- В запросе доступны только секции ИЗ и ГДЕ языка запросов
- В условиях можно указывать параметры сеанса и функциональные опции в качестве параметров запроса (перед именем ставится символ "&")
- В запросе можно использовать вложенные запросы, но вложенные запросы не должны содержать табличные части. Если во вложенном запросе необходимо получить данные из табличной части, то в разделе ИЗ вложенного запроса необходимо обращаться непосредственно к табличной части. Например ... ИЗ Справочник.Контрагенты.Продукция, где Продукция - табличная часть.
- Не допускается применение оператора В ИЕРАРХИИ и предложения ИТОГИ
- Нельзя использовать виртуальные таблицы регистров (например, СрезПоследних или ОстаткиИОбороты)
- В запросе можно использовать шаблоны, упрощающих написание ограничений
- в выражении ограничения может использоваться функция СтрСодержит(ГдеИщем, ЧтоИщем).
- в выражении ограничения может использоваться оператор "+" для конкатенации строк.
Запись считается доступной, если выполняется условие ограничения или в результате работы условия получается непустая таблица. Если ограничения не установлены, то это равносильно ограничению ГДЕ Истина.
Самый простой вариант установки ограничения первого случая на примере таблицы Контрагенты:

Здесь устанавливается ограничение по наименованию. Ограничения устанавливается на всю запись целиком. Будут выведены только те записи, для которых выполняется условие.
В условии можно обращаться к полям реквизитов через точку, например:
Контрагенты ГДЕ Контрагенты.Регион.Наименование = "Москва"
Пример установки ограничения второго варианта:

Здесь запись будет доступна, если есть хоть один товар, у которого поставщиком является контрагент из основной таблицы.
Правила объединения условий:
Если в таблице ограничений доступа несколько строк с указанием разных полей, то условия отбора объединяются по "И".
Если у пользователя несколько ролей с разными правами доступа на одни и те же объекты, то условия объединяются по "ИЛИ"
Особенности построения условий:
Если по условиям RLS требуется объединение по ИЛИ, то надо обязательно условия по ИЛИ заключить в скобках. Если этого не сделать, то система может сформировать некорректный итоговый запрос:
_ДемоПартнеры ГДЕ (_ДемоПартнеры.ЭтоАгент
ИЛИ _ДемоПартнеры.ЭтоГруппа)
Если требуется показывать представления объектов, на которые доступ закрыт, то в таблице ограничений надо выбрать все поля, кроме Ссылка и полей, которые формируют представление (для справочника это наименование)
Сложные условия с подчиненными таблицами
1. Разыменование полей.
_ДемоКонтрагенты ГДЕ _ДемоКонтрагенты.Партнер.ЭтоАгент
2. Связи таблиц (аналог разыменования)
_ДемоКонтрагенты ИЗ Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Справочник._ДемоПартнеры КАК _ДемоПартнеры
ПО _ДемоКонтрагенты.Партнер = _ДемоПартнеры.Ссылка
ГДЕ _ДемоПартнеры.ЭтоАгент
Это 2 самых меделнных варианта, так как сначала объединяются 2 таблицы целиком, а потом накладывается условие.
Более быстрый запрос с внутренним соединением:
_ДемоКонтрагенты ИЗ Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник._ДемоПартнеры КАК _ДемоПартнеры
ПО _ДемоКонтрагенты.Партнер = _ДемоПартнеры.Ссылка
И (_ДемоПартнеры.ЭтоАгент)
3. Вложенный запрос
_ДемоКонтрагенты ГДЕ _ДемоКонтрагенты.Партнер В
(ВЫБРАТЬ
_ДемоПартнеры.Ссылка КАК Ссылка
ИЗ
Справочник._ДемоПартнеры КАК _ДемоПартнеры
ГДЕ
_ДемоПартнеры.ЭтоАгент)
4. Соежинение с вложенным запросом
_ДемоКонтрагенты ИЗ Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
_ДемоПартнеры.Ссылка КАК Ссылка
ИЗ
Справочник._ДемоПартнеры КАК _ДемоПартнеры
ГДЕ
_ДемоПартнеры.ЭтоАгент) КАК ВложенныйЗапрос
ПО _ДемоКонтрагенты.Партнер = ВложенныйЗапрос.Ссылка
На самом деле каждая СУБД сама старается подобрать нужный вариант запроса. Мы можем ей помочь, но это не всегда удается.
Самый быстрый вариант, когда условие накладывается на реквизит основной таблицы без соединения с другими, но это возможно далеко не всегда.
Инструкции препроцессора
В тексте запроса на ограничение доступа к данным можно использовать инструкции препроцессора. Выглядят они следующим образом:
#Если <Выражение> #Тогда
#ИначеЕсли <Выражение> #Тогда
#Иначе
#КонецЕсли
<Выражение> – произвольное логическое выражение на встроенном языке, результат которого имеет тип Булево. Выражение может содержать:
- операции сравнения <, >, <=, >=, =, <>;
- логические операции И, ИЛИ, НЕ;
- параметры сеанса – используется синтаксис &Параметр, где Параметр – имя параметра сеанса.
- параметры шаблона
- функциональные опции (не параметризированные). Используется синтаксис: &ИмяФункциональнойОпции
Если в тексте ограничения используются инструкции препроцессора, то конструктор ограничений не работает.
В языке ограничений используются служебные символы:
& - для обращения к параметрам сеанса и функциональным опциям. Например "ГДЕ Автор = &ТекущийПользователь". Здесь ТекущийПользователь - это параметр сеанса.
# -
-
для инструкций препроцессора (см выше)
-
перед ключевым словом ТекущаяТаблица. Например #ТекущаяТаблица КАК ТекущаяТаблица в ограничении для таблицы Контрагенты равносильно Контрагенты КАК ТекущаяТаблица
-
перед ключевым словом ИмяТекущейТаблицы
-
перед ключевым словом ИмяТекущегоПраваДоступа. Содержит имя права, для которого выполняется текущее ограничение: ЧТЕНИЕ, ДОБАВЛЕНИЕ, ИЗМЕНЕНИЕ, УДАЛЕНИЕ
Шаблоны
Шаблоны записываются в свойствах роли на вкладке "Шаблоны ограничений". По своей сути шаблоны - это макроподстановка текста. При их применении надо следить, чтобы в тексте запроса не задваивались служебные слова, такие как ГДЕ.
Шаблон может иметь параметры: #ИмяШаблона("Значение параметра шаблона 1", "Значение параметра шаблона 2",...). Каждый параметр шаблона заключается в двойные кавычки. При необходимости указания в тексте параметра символа двойной кавычки следует использовать две двойные кавычки.
Для универсальности использования шаблонов можно убрать обращение к псевдонимам таблиц, т.е. вместо "Не _ДемоСчетНаОплатуПокупателю.Ссылка В ()" можно указать "Не Ссылка В ()". Так же имя псевдонима можно удалить до оператора "ГДЕ", т.е. вместо "_ДемоСчетНаОплатуПокупателю ГДЕ #ВсяНоменклатураДляАгентсикхПродажИТЧНеПуста И #ДокПроведен" указать "ГДЕ #ВсяНоменклатураДляАгентсикхПродажИТЧНеПуста И #ДокПроведен". Единственное ограничение: раз уж решили убирать псевдонимы таблиц, то убираем их везде, иначе может выйти ошибка.
В шаблонах символ # также используется:
- перед служебными выражениями такими как :
- ТекущаяТаблица. Есть ограничение: в ранних версиях платформы нельзя использовать обращение к табличным частям через точку: #ТекущаяТаблица.Товары. В текущей версии это допустимо, но в стандартных конфигурациях до сих пор вместо #ТекущаяТаблица.Товары используют #Параметр(1).#Параметр(2) где в качестве параметров передают имя документа и имя табличной части.
- ИмяТекущейТаблицы - обозначает вставку в текст полного имени таблицы (как строковое значение, в кавычках)
- ИмяТекущегоПраваДоступа - содержит имя права, для которого выполняется текущее ограничение: ЧТЕНИЕ/READ, ДОБАВЛЕНИЕ/INSERT, ИЗМЕНЕНИЕ/UPDATE, УДАЛЕНИЕ/DELETE
- перед ключевым словом Параметр. Например текст шаблона ОграничениеПоАвтору: "ГДЕ #Параметр(1) = &ТекущийПользователь". В ограничении доступа вызов #ОграничениеПоАвтору("Автор"). равносильно вызову ГДЕ Автор = &ТекущийПользователь. Вызов #ОграничениеПоАвтору("Ответственный") равносильно ГДЕ Ответственный= &ТекущийПользователь
- перед именем параметра шаблона. Означает вставку в текст ограничения соответствующего параметра шаблона.
- перед символом #. "##" в тексте шаблона равносильно вызову символа "#". Например текст шаблона: ##Если &ИспользоватьОграничениеПоОрганизации ИЛИ ##Тогда ... ##КонецЕсли
Пример использования шаблона в ограничении доступа:
#ОрганизацияПодразделение("Организация", "Подразделение")
пример текста шаблона:
##Если &ИспользоватьОграничениеПоОрганизации ИЛИ &ИспользоватьОграничениеПоПодразделения ##Тогда
ТекущаяТаблица
ИЗ
#ТекущаяТаблица КАК ТекущаяТаблица
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ
СоставГруппы.Ссылка КАК ГруппаПользователей
ИЗ
Справочник.ГруппыПользователей.ПользователиГруппы КАК СоставГруппы
ГДЕ
СоставГруппы.Пользователь = &ТекущийПользователь) КАК ГруппыПользователей
ПО (ИСТИНА)
ГДЕ
НЕ ГруппыПользователей.ГруппаПользователей ЕСТЬ NULL
И
(НЕ 1 В
(ВЫБРАТЬ ПЕРВЫЕ 1
1
ИЗ
РегистрСведений.НазначениеВидовОбъектовДоступа КАК НазначениеВидовОбъектовДоступа
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НастройкиПравДоступаПользователей КАК НастройкиПравДоступаПользователей
ПО
НастройкиПравДоступаПользователей.ОбъектДоступа = ВЫБОР
##Если &ИспользоватьОграничениеПоОрганизации ##Тогда
КОГДА НазначениеВидовОбъектовДоступа.ВидОбъектаДоступа = ЗНАЧЕНИЕ(Перечисление.ВидыОбъектовДоступа.Организации)
ТОГДА ТекущаяТаблица.#Параметр(1)
##КонецЕсли
##Если &ИспользоватьОграничениеПоПодразделения ##Тогда
КОГДА НазначениеВидовОбъектовДоступа.ВидОбъектаДоступа = ЗНАЧЕНИЕ(Перечисление.ВидыОбъектовДоступа.Подразделения)
ТОГДА ТекущаяТаблица.#Параметр(2)
##КонецЕсли
КОНЕЦ
И НастройкиПравДоступаПользователей.ОбъектДоступа ЕСТЬ NULL))
##КонецЕсли
Универсальные шаблоны
В типовых конфигурациях, используются универсальные шаблоны вида:
НЕ ИСТИНА В
(ВЫБРАТЬ ПЕРВЫЕ 1
ИСТИНА
ИЗ
#Параметр(1).#Параметр(2) КАК _ТЧ
ГДЕ
_ТЧ.Ссылка = #ТекущаяТаблица.Ссылка)
Здесь проверяется Истина на вхождение в выборку, которая возвращает Истина, если есть записи. Булевый тип используется так как он самый легкий. Связь таблицы с ссылкой переносится в подзапрос: _ТЧ.Ссылка = #ТекущаяТаблица.Ссылка. Таким образом для текущей ссылки отбираются строки в подчиненной табличной части. Если подзапрос возвращает какие-то записи, то он возвращает Истина. Если записей в подзапросе нет, то условие на Истина в (Выбрать Истина ...) не выполняется.
Копирование шаблонов.
Чтобы скопировать шаблоны доступа на другие роли, надо в конфигураторе выбрать ветку "Роли", нажать правую клавишу и выбрать "Все ограничения доступа". Далее прейти на вкладку "Шаблоны", найти нужный шаблон, выделит его и нажать на кнопку "Копировать шаблоны ограничений". Потом останется только выделить роли в которые надо перенести шаблон.
Что может содержать выражение ограничения
В выражении ограничения доступа могут содержаться:
- Шаблон ограничения доступа, который указывается в формате #ИмяШаблона("Значение параметра шаблона 1", "Значение параметра шаблона 2",...). Каждый параметр шаблона заключается в двойные кавычки. При необходимости указания в тексте параметра символа двойной кавычки следует использовать две двойные кавычки.
- Функция СтрСодержит(ГдеИщем, ЧтоИщем). Функция предназначена для поиска вхождения строки ЧтоИщем в строке ГдеИщем. Возвращает Истина в случае, если вхождение обнаружено и Ложь – в противном случае.
- Оператор + для конкатенации строк.
Рекомендации при разработки ограничений
Рекомендуется проиндексировать реквизиты, которые используются в ограничениях доступа. Это даст возможность СУБД использовать индекс для поиска записей, удовлетворяющих условию ограничения доступа.
Использование нескольких таблиц и соединений в ограничениях доступа приводят к усложнению запроса. Поэтому рекомендуется реквизиты, на которые опирается определение доступности записей, включать в состав самого объекта конфигурации, а не обращаться к ним через точку. Это приведет к хранению избыточной информации, но позволит увеличить скорость выполнения запроса.
На чтение рекомендуется настроить 2 ограничения:
<Прочие поля> - для установки ограничений (запись целиком)
Ссылка, ВерсияДанных, Номер, Дата, (Код, Родитель, Владелец) - без установки ограничений для обеспечения неявного обращения к служебным полям.
Статья на ИТС
Производительный
Об его особенностях можно почитать в статье на ифостарте
Смысл варианта в том, что при обращении к данным не рассчитывается доступ исходя из роли, а заранее рассчитываются ключи доступа к объектам, которые подставляются в запрос. В настройках RLS при этом используется конструкция:
#Если &ОграничениеДоступаНаУровнеЗаписейУниверсально
#Тогда
#ДляОбъекта("")
#Иначе
...
#КонецЕсли
ОграничениеДоступаНаУровнеЗаписейУниверсально позволяет определить используется ли производительный вариант
#ДляОбъекта("") - запускает сам механизм.
Чтобы производительный метод работал надо, чтобы в модуле менеджера объекта была процедура
// СтандартныеПодсистемы.УправлениеДоступом // Позволяет переопределить ограничение, указанное в модуле менеджера объекта метаданных.
//
// См. УправлениеДоступомПереопределяемый.ПриЗаполненииОграниченияДоступа
//
// Параметры:
// Ограничение - Структура - описание параметра см. УправлениеДоступомПереопределяемый.ПриЗаполненииОграниченияДоступа.Ограничение.
//
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
| И ЗначениеРазрешено(ПодразделениеОрганизации)";
КонецПроцедуры
Более подробно о её конструкциях написано в статье.
Если все настроено корректно, то данные о доступе к записям будут храниться в
- справочник КлючиДоступа
- регистр сведений КлючиДоступаКОбъектам
- регистр сведений КлючиДоступаПользователей
При обращении к данными к запросу будет добавлено обращение к регистру КлючиДоступаКОбъектам с отбором по текущему пользователю, что значительно ускорит процесс.
Данные о доступе обновляются регламентным заданием.
|