В Windows существует механизм периодической принудительной смены паролей пользователями с возможностью установки минимально допустимой длины и требований по сложности. В статье рассказывается, как реализовать аналогичный механизм для пользователй базы 1С.
В доменных политиках Windows есть такая удобная штука, как принудительная периодическая смена пароля учетной записи пользователя. Давно хотелось сделать что-то подобное и для 1С-ки.
Реализация выполнена на конфигурации "Альфа-Авто" от "Рарус", но в принципе, с минимальными доработками, портируема и на другие конфигурации.
Всего необходимо внести четыре изменения:
Изменение первое: в раздел "Константы" добавляются две константы (см. пример 1):
1.ПериодическаяСменаПароля - булева типа, по этой константе будет включаться, отключаться периодическая смена пароля.
2. ПериодичностьСменыПароля - Число(3,0) - здесь указывается период в днях, через который потребуется смена пароля.
Эти константы необходимо добавить в экранную форму редактирования констант (см. пример 2). Для удобства администрирования я повесил на событие "ПериодичностьСменыПароляПриИзменении" простую процедуру:
Процедура ПериодическаяСменаПароляПриИзменении(Элемент)
Если ПериодическаяСменаПароля Тогда ТекстВопроса = "Установить "; ЗначениеДляПодстановки = истина; Иначе ТекстВопроса = "Снять "; ЗначениеДляПодстановки = ложь; КонецЕсли;
ТекстВопроса = ТекстВопроса+"у всех пользователей признак ""Периодическая смена пароля""?";
Если Вопрос( ТекстВопроса,РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Пользователи.Ссылка КАК Ссылка |ИЗ | Справочник.Пользователи КАК Пользователи"; РезультатЗапроса = Запрос.Выполнить().Выгрузить(); Размер = РезультатЗапроса.Количество(); Для каждого элПользователь Из РезультатЗапроса Цикл обПользователь = элПользователь.Ссылка.ПолучитьОбъект(); обПользователь.ПериодическаяСменаПароля = ЗначениеДляПодстановки; обПользователь.Записать(); Состояние(Строка(РезультатЗапроса.Индекс(элПользователь))+"/"+Размер); КонецЦикла; КонецЕсли;
КонецПроцедуры
Данная процедура при изменении значения константы "ПериодическаяСменаПароля" предлагает , и при согласии пользователя, изменяет аналогичный реквизит для всех элементов справочника "Пользователи".
Второе изменение, которое необходимо внести, это дополнительные реквизиты справочника "Пользователи"(см. примеры 3,4):
1. Реквизит "ПериодическаяСменаПароля" - булева типа
2. Реквизит "ДатаПоследнейСменыПароля" - типа "Дата", состав "Дата"
Реквизит "ПериодическаяСменаПароля" в справочнике "Пользователи" необходим для того, чтобы можно было отключать смену пароля у части пользователей. Как пример, служебные учетные записи, используемые для автоматического запуска обработок ("Robot", "BackUp" и т.д.).
Третье изменение: в какой-либо из существующих или вновь созданный глобальный модуль добавляются несколько процедур:
Процедура раПроверитьСрокПароля(Пользователь) Экспорт Если раПарольПросрочен(Пользователь) Тогда раСменитьПароль(Пользователь); КонецЕсли; КонецПроцедуры Функция раПарольПросрочен(ТекПользователь) Экспорт Если Константы.ПериодическаяСменаПароля.Получить() Тогда Если ТекПользователь.ПериодическаяСменаПароля Тогда ПериодичностьСменыПароля = Константы.ПериодичностьСменыПароля.Получить() * 24 * 60 * 60; // из количества дней приводим к 1С-кому формату временной разницы
ДатаСменыПароля = НачалоДня(ТекПользователь.ДатаПоследнейСменыПароля + ПериодичностьСменыПароля); Если ДатаСменыПароля <= НачалоДня(ТекущаяДата()) Тогда Возврат истина; КонецЕсли; КонецЕсли; КонецЕсли; Возврат ложь; КонецФункции // ПарольПросрочен(ТекПользователь) Процедура раСменитьПароль(спрПользователь)Экспорт #Если Клиент Тогда
ТекПользователь = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя()); ОбъектПользователь = спрПользователь.ПолучитьОбъект(); ТекстПредупреждения = " В соответствии с политикой информационной безопасности организации"+Символы.ПС+ "пароль пользователя должен изменяться каждые "+Константы.ПериодичностьСменыПароля.Получить()+ " дней."+Символы.ПС+ "---------------------------------------------------------------------------------------------------------------------------------------------"+ Символы.ПС + "Пароль пользователя должен удовлетворять следующим требованиям сложности:"+ Символы.ПС + "---------------------------------------------------------------------------------------------------------------------------------------------"+ Символы.ПС + "Длина не менее "+ПолучитьМинимальнуюДлинуПаролейПользователей()+" символов."+Символы.ПС+ "Содержит не менее 3-х типов символов из перечисленных ниже:"+Символы.ПС+ " заглавные буквы"+Символы.ПС+ " строчные буквы"+Символы.ПС+ " цифры"+Символы.ПС+ " спец.символы"+Символы.ПС+ "Не совпадает с именем пользователя."+Символы.ПС+ "Не является последовательностью символов."; Предупреждение(ТекстПредупреждения,60); ВведенТекущийПароль = ложь; Пока НЕ ВведенТекущийПароль Цикл ТекущийПароль = ""; Подсказка = "Введите текущий пароль"; Если Не ВвестиПароль(ТекущийПароль, Подсказка) Тогда ЗавершитьРаботуСистемы(ложь); Возврат; КонецЕсли; Если ПарольДействует(ТекущийПароль) Тогда ВведенТекущийПароль = истина; КонецЕсли; КонецЦикла; ПарольЗаменен = ложь; Пока НЕ ПарольЗаменен Цикл ТекстПароля1 = ""; Подсказка = "Смена пароля. Введите новый пароль"; Если Не ВвестиПароль(ТекстПароля1, Подсказка) Тогда ЗавершитьРаботуСистемы(ложь); Возврат; КонецЕсли; ТекстПароля2 = ""; Подсказка = "Повторите новый пароль"; Если Не ВвестиПароль(ТекстПароля2, Подсказка) Тогда ЗавершитьРаботуСистемы(ложь); Возврат; КонецЕсли; Если ТекстПароля1<>ТекстПароля2 Тогда Предупреждение("Введенные пароли не совпадают!",10); ИначеЕсли ТекущийПароль = ТекстПароля1 Тогда Предупреждение("Новый пароль не должен совпадать со старым!",10); Иначе ТекПользователь.Пароль=ТекстПароля1; Попытка ТекПользователь.Записать(); ОбъектПользователь.ДатаПоследнейСменыПароля = ТекущаяДата(); ОбъектПользователь.Записать(); ПарольЗаменен = истина; Исключение ТекстОшибки = ОписаниеОшибки(); Место = Найти(ТекстОшибки,"Записать):"); Длина = СтрДлина(ТекстОшибки); ТекстОшибки = Прав(ТекстОшибки,Длина - Место-10); Если ТекстОшибки = "Заданный пароль короче установленной минимальной длины" Тогда ТекстОшибки = ТекстОшибки +": "+ ПолучитьМинимальнуюДлинуПаролейПользователей()+" символов."; КонецЕсли; Если ТекстОшибки = "Заданный пароль не удовлетворяет требованиям сложности" Тогда ТекстОшибки = ТекстОшибки +": "+ Символы.ПС + +"-----------------------------------------------"+ Символы.ПС + "Длина не менее "+ПолучитьМинимальнуюДлинуПаролейПользователей()+" символов."+Символы.ПС+ "Содержит не менее 3-х типов символов из перечисленных ниже:"+Символы.ПС+ " заглавные буквы"+Символы.ПС+ " строчные буквы"+Символы.ПС+ " цифры"+Символы.ПС+ " спец.символы"+Символы.ПС+ "Не совпадает с именем пользователя."+Символы.ПС+ "Не является последовательностью символов."; КонецЕсли; Предупреждение(ТекстОшибки,60); // здесь штатными средствами платформы выдается сообщение, чем пароль не устраивает
КонецПопытки; КонецЕсли; КонецЦикла; ПериодичностьСменыПароля = Константы.ПериодичностьСменыПароля.Получить() * 24 * 60 * 60; ДатаСледующейСмены = спрПользователь.ДатаПоследнейСменыПароля + ПериодичностьСменыПароля; ТекстПредупреждения = "Пароль пользователя изменен."+Символы.ПС+ "Благодарим за понимание."+Символы.ПС+ "Следующая смена пароля: "+Формат(ДатаСледующейСмены,"ДЛФ=DD"); Предупреждение(ТекстПредупреждения,10); #КонецЕсли
КонецПроцедуры Функция ПарольДействует(ТекущийПароль) СтрокаСоединения = СтрокаСоединенияИнформационнойБазы()+" "; Логин = "Usr="""+ИмяПользователя()+"""; "; Пароль = "Pwd="+ТекущийПароль; СтрокаСоединения = СтрокаСоединения + Логин + Пароль; cntr = Новый COMObject("V82.COMConnector"); Попытка connection = cntr.Connect(СтрокаСоединения); ПарольДействует = истина; Исключение ОписаниеОшибки = ОписаниеОшибки(); Если Найти(ОписаниеОшибки,"Неправильное имя или пароль пользователя")>0 Тогда ПарольДействует = ложь; Иначе ПарольДействует = истина; КонецЕсли; КонецПопытки; connection = ""; cntr = ""; Возврат ПарольДействует; КонецФункции Функция ВвестиПароль(ТекстПароля, Подсказка) НоваяФорма = ПолучитьОбщуюФорму("ВводПароля",,"Моя форма"); НоваяФорма.Заголовок = Подсказка; ПароляТекст = НоваяФорма.ОткрытьМодально(); Если ПароляТекст <> Неопределено Тогда ТекстПароля = ПароляТекст; Возврат истина; Иначе Возврат ложь; КонецЕсли; КонецФункции
И, наконец, четвертое изменение:
В процедуру "ПриНачалеРаботы" модуля приложения добавляется вызов процедуры "раПроверитьСрокПароля(ПараметрыСеанса.Пользователь)".
После внесения изменений в конфигурацию, при первом заходе в базу данных необходимо будет установить значение константы "ПериодическаяСменаПароля" в "истина". После этого будет выведено диалоговое окно, предлагающее изменить значение реквизита "ПериодическаяСменаПароля" для всех элементов справочника "Пользователи", что и будет сделано при положительном ответе. Далее, необходимо будет выставить значение константы "Периодичность смены пароля", например - 60. Это значит, что система будет запрашивать смену пароля каждые 60 дней.
Далее, если есть пользователи, у которых не должен периодически меняться пароль, необходимо снять у данных элементов справочника "Пользователи" соответствующую галочку реквизита "Периодическая смена пароля".
Собственно, и вся настройка.
Теперь, при первом последующем заходе пользователя в базу данных у него выйдет диалоговое окно, оповещающее о необходимости смены пароля (см. пример 5).
После этого пользователю будет предложено ввести старый пароль.
Тут позволю себе небольшое отступление:
Понятно, что вновь устанавливаемый пароль пользователя не должен совпадать со старым. Иначе, вся идея смены пароля сливается в никуда. Старый пароль пользователя необходим нам, чтобы сравнить его с новым. К сожалению, пароль пользователя хранится в базе в хэшированном виде и я не нашел способов выдернуть его в пригодном для сравнения с новым паролем виде. Поэтому, мы вынуждены требовать от пользователя ввести старый пароль в открытом виде и проверять, действительно ли введен актуальный пароль от базы.
Для этого мы создаем объект "V82.COMConnector", прописываем в его параметрах путь к базе, имя пользователя и введенный им пароль. После этого пробуем соединиться с базой данных . Если соединение прошло успешно - пароль верный. Если была возвращена ошибка "Неправильное имя или пароль пользователя", то значит, пользователь пытается нас обмануть. Еще возможна ошибка "Данному пользователю не разрешены внешние соединения", но она возникает уже после успешной авторизации. Нас и такой вариант устроит. Пароль ведь верный, а это все, что нам сейчас надо знать.
Далее пользователю предлагается ввести и подтвердить новый пароль (см . пример 6).
Если пароль не удовлетворяет требованиям по сложности, то пользователю будет выведено об этом сообщение (см. пример 7) и будет предложено ввести новый пароль еще раз.
Еще одно отступление:
Параметры сложности паролей пользователей настраиваются в режиме "Конфигуратор", в меню "Администрирование" - "Параметры информационной базы" (см. пример 8). Здесь можно выставить минимально допустимую длину пароля, а проверку сложности пароля пользователя. Пароль в таком случае будет проверяться по наличию как минимум, трех различных групп символов: цифры, большие и маленькие буквы, а также различные раскладки клавиатуры.
Если пользователь не захочет вводить старый или новый пароли, то работы системы будет завершена.
Итак, пользователь успешно ввел новый пароль, отвечающий требованиям безопасности. Теперь, в течение прописанного в константе "ПериодичностьСменыПароля" (например, 60 дней) система оставит пользователя в покое. А по истечении этого срока, вновь потребует сменить пароль.
К сожалению, ничего не мешает пользователю поменять пароль на новый, а затем в пользовательском режиме зайти в "Сервис" - "Параметры пользователя" и там поменять пароль опять на старый. Но для этого необходимо, чтобы пользователь знал об этой возможности, а о ней, как показывает практика знают очень мало пользователей. Для того, чтобы отсечь эту возможность, пришлось бы хранить пароли пользователей в базе в открытом виде, а это, по моему мнению, излишний в данном случае, риск.
И в заключение, несколько моментов организационного порядка:
- Безопасность информации в базе данных должна обеспечиваться комплексом мер, и периодическая смена паролей пользователей, это только одна из них. Описание других мер обеспечения безопасности информации выходит за рамки данной статьи.
- Периодическую смену паролей пользователей в 1С логичнее всего вводить параллельно с введением периодической смены паролей пользователей доменных учетных записей. При этом желательно, выставить одинаковые требования по длине и сложности паролей . Периоды смены паролей лучше тоже выставить одинаковые, но разнести периодичность на пару дней (например, пароли на доменные учетные записи изменялись в понедельник, а на учетные записи 1С – в среду). Это позволит сделать смену паролей менее болезненной для пользователей.
- Введение данного новшества неминуемо столкнется с пассивным, а может, и активным, противодействием пользователей. Наиболее действенным средством, основываясь на практике, служит приказ по организации примерно следующего содержания: «Ответственность за действия, совершенные под учетной записью пользователя, в том числе, и другими лицами, несет сам пользователь. Пользователю запрещается передавать пароли от своих учетных записей другим лицам. Пользователь, отходя от своего рабочего места, обязан заблокировать сессию, во избежание доступа других лиц к ней. Пароли на учетные записи пользователей должны изменяться с периодичностью в 60 дней. За простой, вызванный утерянным паролем от учетной записи, несет ответственность сам пользователь ». С данным приказом следует ознакомить всех пользователей под роспись. Этим сразу снимается колоссальная доля психологической инерции и негатива пользователей.
- В любой, наверно, организации есть пользователи, любящие забывать пароли. После введения данного новшества частота забывания ими пароля гарантировано вырастет в разы. Эффективным средством дисциплинирования таких пользователей служит фиксация фактов внеплановой смены пароля. Причем, вероятнее всего, даже не придется выкладывать данную статистику на стол руководителя. Зачастую пользователю хватает того факта, что тот факт, что он опять забыл пароль, фиксируется, например в «Тетради фиксации внеплановой смены пароля». Чаще всего, пользователь немедленно вспоминает свой пароль.
P.S. Дополнительно хотелось бы прикрутить проверку на несовпадение паролей пользователя Windows и пользователя базы 1С. К сожалению, мне не удалось найти способа сравнения данных паролей.