Двухфакторная аутентификация в 1С




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

17 Comments

  1. tkv44

    Интересная тема. Спасибо автору за исследование.

    В 1С нет подобного, т.к. отсутствует необходимость. Двухфакторная аутентификация нужна там, где проходной двор. А бухгалтеры обычно сидят во внутренней ЛВС, в отдельном кабинете с усиленной дверью (ибо касса тоже рядом). Внедрив подобное, можно заработать много очков в минус карме от тех же бухгалтеров, кому нужен лишний геморрой при входе в программу.

    Reply
  2. Zhilyakovdr

    (1) tkv44, Тема действительно интересная, а применять двухфакторную аутентификацию можно например при работе через веб клиент и предоставлении доступа сторонним лицам.

    Reply
  3. Юрий-К

    (1) tkv44, (2) Zhilyakovdr,

    Спасибо за оценку, на выходных, возможно, в конце статьи размещу пару-тройку скриншотов , чтобы прояснить как заводить секретный ключ в телефон( один человек подсказал),

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

    Меня это «очень сильное колдунство» просто заворожило )).

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

    Вообще функцией HMAC( Знач Ключ, Сообщение ) как раз таки и можно формировать подписи любых данных тк это «..один из механизмов проверки целостности информации, позволяющий гарантировать то, что данные, передаваемые или хранящиеся в ненадёжной среде, не были изменены посторонними лицами…» она же выполняет отчасти некоторое исправление против слабых(коротких) ключей и слабых(коротких) сообщений. Хотя для этих целей в 1С есть более продвинутый объект МенеджерКриптографии.

    Reply
  4. Craig

    (0) тема интересная (в декабре была подобная задачка, пока ее временно отложил), опишите пожалуйста как выглядит процесс. Вот пользователь подошел к компьютеру, включил компьютер, ввел пароль от windows, дальше запускает 1с и что происходит далее? так же интересует вопрос возможно ли навесить определенное ограничение на доступ? К примеру, у пользователя нет прав на проведение документа, а тут пришел админ с волшебной флешкой и провел документ через рабочее место пользователя.

    Reply
  5. I_G_O_R

    Я правильно понимаю, что когда открывается форма «Обработка.ДвухфакторнаяАутентификация.Форма.ФормаПроверки» пользователь фактически залогинен и ему осталось закрыть это окно, чтобы можно было продолжить работать?

    Reply
  6. Юрий-К

    (5) I_G_O_R,

    Если он его закроет закроется 1С. Он должен либо ввести корректный одноразовый пароль который все время меняется либо не зайдет.

    Reply
  7. I_G_O_R

    (6) Форму можно закрыть без последствий, или даже вообще не открывать, в браузере можно выполнить свой javascript, ну или подменить javascript. Для взломщика это не будет проблемой, значит толку от такой защиты нет совсем. Чтобы защита реально работала, нужно использовать РЛС в зависимости от параметра сеанса, а значение параметра сеанса должно зависеть от ввода кода.

    Reply
  8. Юрий-К

    (7) I_G_O_R,

    Во первых здесь рассматривается механизм работы с одноразовыми паролями, связка 1С — генераторы паролей. как вы в дальнейшем это используете ограничено только вашей фантазией.

    можете даже

    …использовать РЛС в зависимости от параметра сеанса, а значение параметра сеанса должно зависеть от ввода кода

    во вторых Вы сможете обойти примитивнейшее?

    ОткрытьФорму(«Обработка.ДвухфакторнаяАутентификация.Форма.ФормаПроверки»,,,,,,    ,        РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс ); 

    и событие

    &НаКлиенте
    Процедура ПриЗакрытии()
    Если не АвторизацияПройдена тогда
    ЗавершитьРаботуСистемы (Ложь);
    КонецЕсли;
    КонецПроцедуры
    

    ? Самому интересно посмотреть, про SSL не забудьте. )).

    и еще напомню это вторая часть авторизации первую стандартную никто не отменял.

    Reply
  9. утюгчеловек

    (8)

    во вторых Вы сможете обойти примитивнейшее? …

    Разумеется. Не трогаем форму 2ФА, жмем F1 — открываем справку. Жмем «перейти по ссылке», набираем что-то типа «e1cib/list/Справочник.Справочник1». Работаем со справочником.

    Взял отсюда: http://forum.infostart.ru/forum87/topic150805/.

    Это говорит только о том, что решение должно быть чуточку сложнее. Но в целом — мне лично понравилось. Жму звезду.

    Reply
  10. Юрий-К

    (9) утюгчеловек,

    Это говорит только о том, что решение должно быть чуточку сложнее. Но в целом — мне лично понравилось. Жму звезду.

    это говорит что у меня и у 1С разные понимания ключа

    РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс

    , думаю что рано или поздно 1С исправит этот недочет.

    За звезду спасибо!

    Reply
  11. grandexpert

    Добрый день. Приобрел обработку, дт-шник, лайкнул… но что-то не получается ввести правильный код.

    Порядок действий сделал такой:

    1. Открыл под Админом в базе обработку. Создал секретный ключ.

    2. Скачал Google Authenticator. Сканировал им QR код из обработки.

    3. Ввожу пароль из приложения в 1С. Ругается что неверный пароль.

    4. Время одинаковое между компом и телефоном. По крайней мере по минутам точно.

    В чем может быть причина?

    Reply
  12. Юрий-К

    (11) Добрый день,

    1. Чтобы не было вопросов к синхронизации времени поставьте на смартфоне «синхронизировать время по сети»,

    «использовать 24-часовой формат» , и «использовать часовой пояс сети» , тоже самое на ПК. и попробуйте снова создать 2фа.

    2. Используйте на смартфоне генератор паролей Freeotp

    https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp

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

    и пишите в ЛС.

    Reply
  13. gonyav

    Функция МассивВДвоичныеДанные без COM для 8.3.6 и выше:

    Функция МассивВДвоичныеДанные( КлючМассив ) Экспорт
    ИмяФайла = ПолучитьИмяВременногоФайла( «bak» );
    МассивКоличество = КлючМассив.Количество()-1;
    Запись = Новый ЗаписьДанных(ИмяФайла);
    
    Для Индекс=0 По МассивКоличество  Цикл
    Запись.ЗаписатьБайт(КлючМассив[Индекс]);
    КонецЦикла;
    Запись.Закрыть();
    ДвДанные = Новый ДвоичныеДанные ( ИмяФайла );
    УдалитьФайлы( ИмяФайла);
    Возврат ДвДанные;
    КонецФункции
    

    Показать

    Reply
  14. gonyav

    Генерация QR-кода на сервере linux без БСП:

    &НаСервере
    
    Процедура СоздатьQRКодНаСервере()
    ВремФайл = ПолучитьИмяВременногоФайла(«png»);
    // apt-get install qrencode
    СтрокаВыполнения = «qrencode -o » + ВремФайл + » -t PNG «»otpauth://totp/» + НРег(Транслитерация(Объект.Наименование)) + «@domain.ru?secret=» + Объект.СекретныйКлюч + «»»»;
    ЗапуститьПриложение( СтрокаВыполнения,, Истина);
    КартинкаСервер = Новый Картинка(ВремФайл);
    АдресВоВременномХранилище = ПоместитьВоВременноеХранилище(КартинкаСервер, Новый УникальныйИдентификатор);
    Картинка = АдресВоВременномХранилище; //qr-код на форме
    УдалитьФайлы(ВремФайл);
    КонецПроцедуры
    

    Показать

    Reply
  15. Юрий-К

    (13) Да, спасибо, давно делал, кажется в момент публикации эти объекты уже появились, переделывать было некогда, будет время обновлю обязательно!

    Reply
  16. elephant_x

    Подскажите пожалуйста как сделать что бы пароль был 4-х значный и интервал на вводне 30 секунд, а например 60.

    Что-то не пойму.

    Reply
  17. Юрий-К

    (16) все в коде есть, смотрите внимательней. Какой одноразовый пароль на мобильном устройстве создает генератор оп? в 1С под него подстраивайтесь.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *