- PVSM.RU - https://www.pvsm.ru -

Опыт передачи файлов большого объема по защищенному протоколу из 1С на сайт

Опыт передачи файлов большого объема по защищенному протоколу из 1С на сайт
Во время создания очередной B2B-системы на этапе интеграции 1С: Предприятие 8.2 с web — интерфейсом возникла необходимость безопасной передачи файлов больших размеров из 1С в web.
Для решения этой задачи был выбран протокол SFTP, как надежный и не имеющий ограничений по размеру передаваемого файла.
Во встроенном языке 1С: Предприятие 8.2 отсутствуют функции для передачи данных через SFTP [1], поэтому пришлось искать прикладные средства. На интернет-ресурсах, посвященных программированию 1С, есть примеры удачного использования freeware утилит типа WinSCP [2]. Для использования данного способа необходимо из встроенного языка 1С выполнить запуск утилиты с параметрами командной строки.

Пример запуска утилиты WinCSP из 1С:

КомандаВыгрузки = Символ(34)+Строка(ПутьКПапкеХранилищаФТПФайлов)+""+ "WinSCP.com"+Символ(34)+"/script="+Символ(34)+Строка(ПутьКПапкеХранилищаФТПФайлов)+Символ(34)+"script.txt "+"/parameter "+Символ(34)+Адрес+Символ(34)+" "+
Символ(34)+Ключ+Символ(34)+" "+Символ(34) + Подпапка + Символ(34) + " " + 
Символ(34) + ИмяФайлаОтправки + Символ(34);

Минусом такого решения является отсутствие возможности контроля ошибок запуска и выполнения из встроенного языка 1С. В связи с этим было принято решение написать внешнюю DLL компоненту для 1С: Предприятие 8.2.

Платформа 1С: Предприятие поддерживает две технологии создания внешних компонент Native API и COM. Выбор пал на Native API, так как компоненты, созданные по этой технологии работают как на клиенте, так и на сервере 1С. Используя материалы диска ИТС о технологии создания внешних компонент и open source библиотеки С++, был создан файл SftpExtension.dll (Скачать исходники можно тут [3]).

Создание компоненты DLL

1. Для использования в компоненте протокола SFTP мы использовали две библиотеки.
— libssh http://www.libssh2.org/ [4] (Скачиваем “git clone git://git.libssh2.org/libssh2.git”)
— openssl http://www.openssl.org/ [5] (Скачиваем архив openssl-1.0.1c.tar.gz от сюда [5])
Подключаем библиотеки к проекту.

2. Каждый объект компоненты должен наследоваться от абстрактного класса IcomponentBase и IlanguageInterface.

  • IcomponentBase — реализует основные методы компоненты.
  • IlanguageInterface — служит для локализации методов и свойств 1С и С++ через определения массивов соответствий и методов акцессоров GetMethodName, GetPropName.

Часть кода компоненты описывающая возможность вызова функций С++ из 1С на русском языке:
При этом можно использовать другие языки.

static wchar_t *g_MethodNames[] = { L"SendFile",L"StartSession", L"EndSession", L"IsSessionStart",L"SetSshHost",L"SetSshLogin",L"SetSshPass",L"SetSftpPath",L"SetLocalPath"};


static wchar_t *g_MethodNamesRu[] = { 
L"ПослатьФайл",L"НачатьСессию",L"ЗакончитьСессию",L"ЕслиСессияНачата",
		L"УстановитьХост",L"УстановитьЛогин",L"УстановитьПароль", L"УстановитьУдаленныйПуть",L"УстановитьЛокальныйПуть"};



const WCHAR_T* SftpExtension::GetMethodName(const long lMethodNum, const long lMethodAlias)
{ 
    if (lMethodNum >= eMethLast)
        return NULL;

    wchar_t *wsCurrentName = NULL;
    WCHAR_T *wsMethodName = NULL;
    int iActualSize = 0;

    switch(lMethodAlias)
    {
    case 0: // First language
        wsCurrentName = g_MethodNames[lMethodNum];
        break;
       case 1: // Second language
        wsCurrentName = g_MethodNamesRu[lMethodNum];
        break;
    default: 
        return 0;
   }

    iActualSize = wcslen(wsCurrentName)+1;

    if (m_iMemory && wsCurrentName)
    {
        if(m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T)))
            ::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize);
    }

    return wsMethodName;
}

3. Для вызова необходимой функции из компоненты используется метод CallAsFunc из интерфейса IcomponentBase. При вызове методов из компоненты 1С, вызывается этот С++ метод.

В качестве параметров метода используются:

  • lMethodNum – номер метода в массиве соответствий.
  • pvarRetValue – указатель на выходные параметры.
  • paParams — параметры из метода в 1С.
  • lSizeArray – размер массива, если входной параметр массив.
bool SftpExtension::CallAsFunc(const long lMethodNum,
                tVariant* pvarRetValue,tVariant* paParams, const long lSizeArray){

switch(lMethodNum){

		case eMethSendFile: 
		{	
		
			if (!lSizeArray || !paParams)
					return false;

			this->local_path = toChar(paParams);			
			WriteToServer(status, this->local_path); //
			pvarRetValue->pstrVal = status; //status

			pvarRetValue->strLen = strlen(pvarRetValue->pstrVal);
			TV_VT(pvarRetValue) = VTYPE_PSTR;
	            
			ret = true;
			break;
		}	}
return ret;
}

4. В нашем примере из 1С можно выполнять 4 метода, которым соответствуют С++ методы в DLL компоненте.

1С (методы) С++ методы
НачатьСессию()
Предварительно нужно определить параметры авторизации(хост, связку логин, пароль – либо rsa ключи, путь на удалённом сервере).
Поэтому функция НачатьСессию обрастает свойствами: Хост, Логин, Пароль, УдаленныйПуть
StartSSHSession(status,this->ssh_host,this->ssh_login,this->ssh_pass);
StartSftpSession(status,this->sftp_path)
ПослатьФайл(“Путь и имя файла на клиентской машине”) WriteToServer(const char * &status, const char *loclfile)
ЕслиСессияНачата() isSessionStart()
ЗакончитьСессию() endSession() – завершает SFTP сеанс и SSH сеанс

5. В С++ нужно определить параметры доступа(чтение/запись) к созданным свойствам за это отвечают два метода IsPropReadable и IsPropWritable.

bool SftpExtension::IsPropReadable(const long lPropNum)
{
	switch(lPropNum)
	{ 
  	case ePropSshHost:
        	return true; 
	default:
    	return false;
	} 
	return false;}

Таблица соотношений свойств 1С и С++

1С(свойства) С++ свойства
Хост ssh_host
Логин ssh_login
Пароль ssh_pass
УдаленныйПуть Sftp_path

Готовую библиотеку можно скачать тут [6].

Работа с компонентой во встроенном языке 1С

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

ПодключитьВнешнююКомпоненту("C:SftpExtensionSftpExtension.dll","Компонента",ТипВнешнейКомпоненты.Native);
Компонента = Новый("AddIn.Компонента.SftpExtension");

2. Заполняем 4 свойства объекта компоненты Хост, Логин, Пароль, УдаленныйПуть.

Компонента.Хост = "192.168.0.1";
Компонента.Логин = "root";
Компонента.Пароль = "123";
Компонента.УдаленныйПуть = "/var/www/company/data/www/import/data.xml";

3. Открываем сессию соединения

Компонента.НачатьСессию();

4. Отправляем файл

Компонента.ПослатьФайл("C:data.xml");

5. Отправляем следующий файл, с проверкой открыта ли сессия соединения.

Если Компонента.СессияНачата() Тогда
      Компонента.ПослатьФайл("C:data2.xml");
Иначе
   Компонента.НачатьСессию();
   Компонента.ПослатьФайл("C:data2.xml");
КонецЕсли;

6. После отправки файлов закрываем сессию

Компонента.ЗакончитьСессию();

В результате выполнения успешно был передан файл с C:data2.xml в /var/www/company/data/www/import/data.xml.

Используемые материалы
Литература:
Мануал по созданию компоненты [7]
Библиотеки для работы по SFTP:

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

Автор: Centrobit

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/e-lektronnaya-kommertsiya/24561

Ссылки в тексте:

[1] SFTP: http://ru.wikipedia.org/wiki/SFTP

[2] WinSCP: http://winscp.net/eng/index.php

[3] тут: http://centrobit.ru/download/1ckomponent/source.zip

[4] http://www.libssh2.org/: http://www.libssh2.org/

[5] http://www.openssl.org/: http://www.openssl.org/

[6] тут: http://centrobit.ru/download/1ckomponent/dll.zip

[7] Мануал по созданию компоненты: http://st.free-lance.ru/projects/upload/f_4d5118dcf1abb.pdf

[8] Источник: http://habrahabr.ru/post/165441/