Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Волшебство программирования на 1С:Предприятие 7.7 и 8.0



Волшебство программирования на 1С:Предприятие 7.7 и 8.0


v8: Авторизация пользователей при входе в программу

Рассматривается для 1С версии 8.1.Автор статьи: PR (Печёнкин Роман)
URL: http://kb.mista.ru/article.php?id=455

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

Но как правило, наряду с заведением пользователей в конфигураторе имеет смысл сделать в конфигурации справочник "Пользователи", в котором хранить пользователей, соответствующих пользователям в конфигураторе.
Это дает возможность некоторых вещей, например привязки к пользователю некоторых прав, которыми нельзя управлять с помощью метаданного "Роль", построение системы ограничения прав RLS, привязанной к текущему пользователю, сохранение в справочниках и документах информации об авторах объектов, индивидуальные особенности интерфейса, настроек отчетов, событий и т. д.

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

Итак. Для выполнения этой задачи в конфигурации требуется сделать нижеперечисленные настройки.

Добавляем в конфигурацию план обмена "РаспределенныеБазы".

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

Добавляем в конфигурацию параметр сеанса "ТекущийПользователь" типа "СправочникСсылка.Пользователи".

Добавляем в конфигурацию параметр сеанса "ТекстСообщенияОбОшибкеПриЗапускеПрограммы" типа "Строка неограниченной длины".

Добавляем в конфигурацию параметр сеанса "ТекущийУзелРаспределеннойБазы" типа "ПланОбменаСсылка.РаспределенныеБазы".

Добавляем в конфигурацию константу "ЗапретитьЗапускПрограммыНовымПользователям" типа "Булево".

В модуль приложения в процедуру ПередНачаломРаботыСистемы() вставляем код
Если ПараметрыСеанса.ТекущийПользователь.Пустая() Тогда
    Предупреждение(ПараметрыСеанса.ТекстСообщенияОбОшибкеПриЗапускеПрограммы, 60);
    Отказ = Истина;
КонецЕсли;


В модуль внешнего соединения в процедуру ПриНачалеРаботыСистемы() вставляем код
Если ПараметрыСеанса.ТекущийПользователь.Пустая() Тогда
    ВызватьИсключение(ПараметрыСеанса.ТекстСообщенияОбОшибкеПриЗапускеПрограммы);
    Отказ = Истина;
КонецЕсли;


В модуль сеанса, в котором фирма "1С" рекомендует устанавливать параметры сеанса, в процедуру УстановкаПараметровСеанса() вставляем код
ПараметрыСеанса.ТекущийУзелРаспределеннойБазы = ПланыОбмена.РаспределенныеБазы.ЭтотУзел();
глУстановитьПараметрСеансаТекущийПользователь();


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

Функция глЕстьДействующиеПользователи()
    
    ТекстЗапроса =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Пользователи.Ссылка КАК Пользователь
    |ИЗ
    |    Справочник.Пользователи КАК Пользователи
    |ГДЕ
    |    (НЕ Пользователи.ПометкаУдаления)
    |    И Пользователи.Владелец = &Владелец
    |    И (НЕ Пользователи.ЭтоГруппа)";
    
    Запрос = Новый Запрос(ТекстЗапроса);
    Запрос.УстановитьПараметр("Владелец", ПараметрыСеанса.ТекущийУзелРаспределеннойБазы);
    Результат = Запрос.Выполнить();
    
    Если Результат.Пустой() Тогда
        Возврат Ложь;
    Иначе
        Возврат Истина;
    КонецЕсли;
    
КонецФункции


Собственно все. Теперь программа не запустится, если список пользователей в конфигураторе пустой.

И напоследок немного по логике работы.

Параметр сеанса "ТекущийПользователь" вместо комбинации двух одноименных экспортных переменных "глТекущийПользователь" в модуле приложения и модуле внешнего соединения выбран потому, что к нему можно привяхать RLS, а к глобальной переменной нет.

Параметр сеанса "ТекстСообщенияОбОшибкеПриЗапускеПрограммы" заведен исключительно для того, чтобы определить, что пользователь неавторизован и что-то нужно сказать этот самый текст перед принужительным завершением работы программы.
Если устанавливать параметры сеанса в модуле приложения в процедуре ПередНачаломРаботыСистемы() и в модуле внешнего соединения в процедуре ПриНачалеРаботыСистемы(), то этот объект метаданных совершенно не нужен, но, раз уж фирма "1С" рекомендует устанавливать параметры сеанса в модуле сеанса...

Константа "ЗапретитьЗапускПрограммыНовымПользователям" создана для того, чтобы при необходимости запретить автоматически программно создавать новых пользователей в справочнике "Пользователи". Может пригодиться в принципе кому-нибудь.

В модуле внешнего соединения проверка авторизованности пользователя выполняется в процедуре ПриНачалеРаботыСистемы(), а не в процедуре ПередНачаломРаботыСистемы() потому, что в модуле внешнего соединения нет события ПередНачаломРаботыСистемы().
Именно поэтому отказаться от запуска программы уже нельзя, но... нужно, поэтому вызываем исключение с заданным текстом ошибки.

В процедуре глУстановитьПараметрСеансаТекущийПользователь() производится попытка авторизовать пользователя, в случае неудачи параметр сеанса "ТекущийПользователь" остается неустановленным, зато устанавливается параметр сеанса "ТекстСообщенияОбОшибкеПриЗапускеПрограммы".
Пользователь останется неавторизованным в том случае, если:
- Имя пользователя пустое, то есть список пользователей в конфигураторе пустой;
- Имя пользователя длиннее размерности наименования справочника "Пользователи";
- Пользователя нет в справочнике "Пользователи", при этом запрещено запускать программу новым пользователям и в справочнике "Пользователи" есть хоть один пользователь.
Проверка на наличие хотя бы одного пользователя в справочнике "Пользователи" делается для того, чтобы не получилось ситуации, когда в программе установили константу "ЗапретитьЗапускПрограммыНовымПользователям", удалили всех пользователей в справочнике "Пользователи", закрыли программу и... больше никогда не смогли в нее зайти;
- Пользователя нет в справочнике "Пользователи", при этом разрешено запускать программу новым пользователям или в справочнике "Пользователи" нет ни одного пользователя, но при попытке создать пользователя произошла какая-то ошибка и пользователь не создался.

Да, и еще напоследок. Не забывайте, что модуль сеанса выполняется в привелигированном режиме, а поэтому можно смело закрывать права на справочник "Пользователи" тем пользоватям, кто недостоин столь высоких прав. Я сказал можно? Нужно!

Официальный сайт рассылки - www.mista.ru
Волшебный форум -
www.forum.mista.ru
Книга знаний - www.kb.mista.ru

С уважением,
Станислав Митичкин (Волшебник)
stasmit@mail.ru



В избранное