Да и в целом, по моему глубокому убеждению, открытость кода в 1С – это одно из важнейших (если не самое важное) её достоинств. Поэтому я сторонник «установки пароля на модуль, поставки без исходного текста», только в случае демо-версии разработки. А при приобретении обработки, клиент приобретает её ЦЕЛИКОМ, в том числе и исходный код.
Для начала, немного общих моментов. Для того что бы ограничить использование нашего «уникального» функционала, будь-то алгоритм проведения документа или процедура формирования отчета, необходимо вынести код в модуль объекта и скрыть его от пользователя. Это можно достичь двумя путями. Во-первых установка пароля на модуль объекта. Что бы установить пароль, откройте модуль объекта, далее в меню «Текст» выберите пункт «Установить пароль». Во-вторых поставка без исходного кода. Что бы получить обработку/отчет без исходного кода, необходимо сначала создать поставку включающую в себя наш отчет без исходного кода, а затем сохранить его как внешний. Настройка поставки производится в диалоге «Конфигурация > Поставка конфигурации > Настройка поставки».
Итак, пример № 1. Ограничение по времени использования. Заключается в том, что функционал работает в течении определенного, ограниченного времени, например 10 дней. Для этого, нам надо как-то «запомнить» дату первого запуска, сделаем это с помощью реестра Windows.
Функция СрокДемоЗакончился() Перем Значение; RegProv=ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv"); // 2147483649 - раздел реестра HKEY_CURRENT_USER RegProv.GetStringValue("2147483649","Software\1C\1Cv8\Report","StartDate",Значение); Если Значение=NULL Тогда // Ключ ещё не создан, считаем этот запуск первым // Создадим ключ, установив значение в текущую дату RegProv.CreateKey("2147483649","Software\1C\1Cv8\Report"); // создание раздела // установка значения для ключа RegProv.SetStringValue("2147483649","Software\1C\1Cv8\Report","StartDate",Строка(Формат(ТекущаяДата(),"ДФ=ггггММддЧЧммсс"))); Возврат Ложь; Иначе // проверка срока использования демо-версии ДатаСтарта=Дата(Значение); КонецПериода=ДатаСтарта+60*60*24*10; // 10 дней ТекДата=ТекущаяДата(); Возврат НЕ (ТекДата>ДатаСтарта И ТекДата<=КонецПериода); КонецЕсли; КонецФункции
Таким образом, осталось только вставить проверку на продолжение работы в нашу основную процедуру, например:
Процедура СформироватьОтчет() Экспорт Если СрокДемоЗакончился() Тогда Возврат; КонецЕсли; … КонецПроцедуры
Для особо хитрых пользователей, можно сделать запрос точного времени из Интернета, что бы защититься от изменения системного времени. Например, так:
Функция ТочноеВремяПоГринвичу() XMLHTTP=Новый COMОбъект("MSXML2.XMLHTTP"); XMLHTTP.Open("get","http://ntp.greenwichmeantime.com/time/scripts/clock-7/x.php",Ложь); XMLHTTP.Send(); UTC=Цел(XMLHTTP.Responsetext/1000); // в секундах Возврат '19700101000000'+UTC+60*60*4; // по Москве, летнее время КонецФункции
Функция СрокДемоЗакончился () Перем Значение; RegProv=ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv"); RegProv.GetDWORDValue("2147483649","Software\1C\1Cv8\Report","Count",Значение); ЭтотЗапуск=1; Если Значение=NULL Тогда RegProv.CreateKey("2147483649","Software\1C\1Cv8\Report"); Иначе ЭтотЗапуск=Значение+1; КонецЕсли; Если ЭтотЗапуск<=5 Тогда RegProv.SetDWORDValue("2147483649","Software\1C\1Cv8\Report","Count",ЭтотЗапуск); Возврат Ложь; Иначе Возврат Истина; КонецЕсли; КонецФункции
Суть этого способа состоит в том, что при запуске у клиента формируется некий уникальный ключ, для которого, по только нам известному алгоритму, можно сформировать «ответный пароль». И в случае совпадения пары ключ-ответ обработка считается успешно зарегистрированной.
В качестве такого уникального ключа можно, к примеру, использовать серийный номер жесткого диска, MAC-адрес, имя пользователя и т.д. Рассмотрим пример с серийным номером жесткого диска.
Функция ПолучитьСерийныйНомерЖесткогоДиска(Диск) ФСО=Новый COMОбъект("Scripting.FileSystemObject"); ФСО_Диск=ФСО.GetDrive(Диск); Возврат ФСО_Диск.SerialNumber; КонецФункции
Алгоритм получения «ответного значения» по ключу, ограничен лишь Вашей фантазией. Здесь же, в качестве примера, я буду использовать простую перестановку символов в обратном порядке.
Функция ПолучитьОтветПоКлючу(Ключ) н=СтрДлина(Ключ); Результат=""; Пока н<>0 Цикл Результат=Результат+Сред(Ключ,н,1); н=н-1; КонецЦикла; Возврат Результат; КонецФункции
Таким образом, наша процедура проверки и подтверждения регистрации будет выглядеть так:
Функция ЭтоЗарегистрированнаяКопия() Перем Значение,Ответ; RegProv=ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv"); RegProv.GetDWORDValue("2147483649","Software\1C\1Cv8\Report","Registered",Значение); Если Значение=NULL Тогда // необходима регистрация копии Регистрация=Ложь; Ключ=ПолучитьСерийныйНомерЖесткогоДиска("C"); Если ВвестиСтроку(Ответ,"Ключ: "+Ключ) Тогда Если Ответ=ПолучитьОтветПоКлючу(Ключ) Тогда // подтвердим регистрацию RegProv.SetDWORDValue("2147483649","Software\1C\1Cv8\Report","Registered",1); Регистрация=Истина; Иначе Предупреждение("Регистрационный код введен не верно!"); КонецЕсли; КонецЕсли; Возврат Регистрация; Иначе // эта копия уже зарегистрированна Возврат Истина; КонецЕсли; КонецФункции
Осталось только вставить проверку регистрации в нашу основную процедуру:
Процедура СформироватьОтчет() Экспорт Если НЕ ЭтоЗарегистрированнаяКопия() Тогда // работа в демо-режиме ... КонецЕсли; ... КонецПроцедуры
Начиная с Windows Script 5.0, появилась возможность чтения зашифрованных сценариев машинами сценариев. Поэтому любой сценарий написанный на VBScript или JavaScript, может быть выполнен в зашифрованном виде. Что бы преобразовать код на VBScript в зашифрованный вид, воспользуемся бесплатной утилитой «Windows Script Encoder», которую можно скачать с сайта Microsoft. В результате, например скрипт создания в реестре Windows раздела «HKEY_CURRENT_USER\Software\1C\1Cv8\Report», будет выглядеть следующим образом:
#@~^ZAAAAA==jY~UtVV{ZMnlD+64N+^OvJU^DbwYcj4+^Vr#@#@&j4VsR"noqDrOPJuF;jw?KWDhCM+'FZ'F;-%'InwKDOwr~\(HE^V@#@&hyAAAA==^#~@
Приведу пример функции, осуществляющей проверку введенного пользователем регистрационного кода, с использованием шифрованного скрипта:
Функция ПроверитьРегистрационныйКод(Код) Скрипт=Новый COMОбъект("MSScriptControl.ScriptControl"); Скрипт.Language="VBScript.Encode"; Скрипт.AddCode("#@~^ewAAAA==o!x^DkKxP;t"+Символ(127)+"^3v|nX*@#@&7zx/SnD{\4wCs/"+Символ(127)+"@#@&d(0~F"+Символ(127)+"XxJ9^+Rl{qOv0q*rPPt"+Символ(127)+"U,bUkh"+Символ(127)+"D'74:.E"+Символ(127)+"P3x9P(W@#@&d;4+13'zUdh"+Символ(127)+"D@#@&3x[~wEUmDrW hyQAAA==^#~@ "); Возврат Скрипт.CodeObject.Check(Код); КонецФункции
Эта функция вернет «Истина», если в качестве регистрационного кода передать ей строку «dce8a7196f14». Аналогичным образом можно скрыть и всю работу с реестром. Но, тем не менее, не следует забывать о существующих специализированных программных продуктах, позволяющих отслеживать чтение и запись реестра.
В заключении, хочется сказать, что как известно, надежная защита для программного продукта – это такая защита, стоимость взлома которой, превышает стоимость законного приобретения. Поэтому для крупных проектов следует использовать более надежные средства от незаконного копирования и использования, такие как вынос ключевых функций во внешние dll, аппаратные ключи защиты и пр. Здесь же я попытался привести несколько простых примеров в качестве основ так сказать…