» » Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE

Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE

13.02
80
51 898
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


Ни для кого не секрет, что вопрос защиты своего php-скрипта рано или поздно встаёт перед любым разработчиком и сегодня я покажу как просто и эффективно защитить свой скрипт на практическом примере - на простеньком модуле для DLE.

Как то давно я навскидку написал простой модуль вывода информации об аттачменте в любом месте сайта - ShowAttach, но до ума модуль не довёл и публиковать его не стал. Вот этот модуль и возьмём за основу для защиты.
Так же нам понадобятся прямые руки и система PCP-CS от Олега Mofsy.

Что такое pcp-cs


PCP-CS — PHP Code Protect Client-Server. Другими словами клиент-серверное приложение для привязки скриптов к определенным ограничениям (домен, ip сервера и т.д.).

Как работает?


Очень упрощенная схема выглядит так:
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


Ключевые преимущества


  • Лёгкая интеграция в нужный скрипт. Достаточно вставить код клиента в скрипт и прописать необходимые параметры
  • Встроенная админка для управления серверной частью. Система имеет встроенную административную часть для управления лицензиями, просмотра логов и т.п.
  • Продуманная реализация проверок. Проверки лицензии осуществляются сначала из локального ключа, и если период проверки истёк - данные запрашиваются с сервера проверки, и если сервер проверки недоступен - защищаемый скрипт не перестанет функционировать в течении заданного периода времени.


Установка и настройка серверной части PCP-CS


Т.к. на момент написания статьи встроенная админка системы не достаточно функциональна, я буду использовать стороннюю админку, написанную специально для этой системы.
Настройку можно производить как на хостинге, так и на локальной машине. Для локалки рекомендую OpenServer.

  1. Скачиваем с гитхаба админку по кнопке "Download ZIP". Она уже содержит последнюю версию серверной части pcp-cs, так что на данном этапе больше ничего не потребуется.
  2. Распаковываем папку upload в корень.
  3. Выполняем запрос из sql.sql. Если необходимо сразу завести пользователя, то выполняем запрос:
    INSERT INTO `pcp_users` (`user_id`, `email`, `password`, `name`, `user_group`) VALUES (1, 'admin@admin.ru', 'c3284d0f94606de1fd2af172aba15bf3', 'admin', 1);
    логин и пароль в этом случаи будут admin, admin
  4. Настраиваем конфиг в трёх файлах:
    admin/config/db_config.php - Конфиг БД
    admin/config/config.php - Конфиг админки
    api/config.php - Конфиг pcp-cs
    Такое разделение обусловлено независимостью админки от серверной части pcp-cs.
  5. Всё! Адинка готова к работе. Можно приступать к защите подопытного модуля.
    Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE



Внедрение клиентской части


Прежде всего необходимо настроить серверную часть.
Для этого создаём новый метод проверки данных.
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE

Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


после успешного создания метода идём в раздел "Лицензии" и добавляе новый лицензионный ключ.
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE

Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


В результате получаем лицезионный ключ, который в дальнейшем можно отдавать покупателю модуля.

Вот теперь можно внедрять непосредственно код клиента!

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


Вот такой внешний вид вывода данных этим модулем:
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


Нам необходимо заблокировать работу скрипта, если он используется без лицензии.

Для начала добавим в конфиг модуля параметр key, в который будем передавать полученный лицензионный ключ.
'key' => !empty($key) ? $key : false,

и завернём рабочий код в условие с проверкой этого параметра, а так же добавим отдельное условие для вывода сообщения об отсутствии ключа.
// Если есть ключ и задан ID новости — работаем
if ($cfg['newsId'] && $key) {
......
} elseif (!$key) {
$showAttach = '<span style="color: red;">Не указан лицензионный ключ.</span>';
}
echo $showAttach;

результат:
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


Добавляем в строку подключения ключ и проверяем:
Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


Теперь нужно добавить проверку введённого ключа с помощью pcp-cs.
  1. Внедряем код клиента в наш модуль. Для экономии ресурсов рекомендую сжать код клиентского класса через любой удобный инструмент. Я использовал сервис PHP-Minifier. Вставляем полученный код перед основным кодом модуля. Если при проверке выдаёт ошибку:
    Fatal error: Namespace declaration statement has to be the very first statement in the script in

    просто удалите этот код:
    namespace MofsyLicenseClient;

  2. Сразу после кода клиентского класса можно его задействовать и произвести проверку.
    В комментарияк к коду ниже я расписал что и как происходит.
    // Теперь можно запустить проверку лицензии
    $protect = new Protect();

    // Секретный ключ из созданного метода проверки
    $protect->secret_key = 'mqgAqWnSwZZM8YX7BEd9';

    // Куда будем класть локальный (зашифрованный) ключ?
    $protect->local_key_path = ENGINE_DIR . '/data/';

    // Имя и расширение локального ключа
    $protect->local_key_name = 'showattach.lic';

    // Адрес сервера проверки
    $protect->server = 'http://pcp-cs.loc/api.php';

    // Дата релиза модуля (пригодится если лицензия даётся на определённую версию модуля)
    $protect->release_date = '2015-02-10';

    // Ключ активации (лицензионный ключ), тот, который передаётся в параметрах строки подключения модуля
    $protect->activation_key = $key;

    // Сообщения о различных ошибках
    $protect->status_messages = array(
    'status_1' => '<span style="color:green;">Активна</span>',
    'status_2' => '<span style="color:darkblue;">Внимание</span>: срок действия лицензии закончился.',
    'status_3' => '<span style="color:orange;">Внимание</span>: лицензия переиздана. Ожидает повторной активации.',
    'status_4' => '<span style="color:red;">Ошибка</span>: лицензия была приостановлена.',
    'localhost' => '<span style="color:orange;">Активна на localhost</span>: используется локальный компьютер, на реальном сервере произойдет активация, если вы правильно ввели лицензионный ключ активации в настройках.',
    'pending' => '<span style="color:red;">Ошибка</span>: лицензия ожидает рассмотрения.',
    'download_access_expired' => '<span style="color:red;">Ошибка</span>: ключ активации не подходит для установленной версии. Пожалуйста поставьте более старую версию продукта.',
    'missing_activation_key' => '<span style="color:red;">Ошибка</span>: ключ активации не указан.',
    'could_not_obtain_local_key' => '<span style="color:red;">Ошибка</span>: невозможно получить новый локальный ключ.',
    'maximum_delay_period_expired' => '<span style="color:red;">Ошибка</span>: льготный период локального ключа истек.',
    'local_key_tampering' => '<span style="color:red;">Ошибка</span>: локальный лицензионный ключ поврежден или не действителен.',
    'local_key_invalid_for_location' => '<span style="color:red;">Ошибка</span>: локальный ключ не подходит к данному окружению.',
    'missing_license_file' => '<span style="color:red;">Ошибка</span>: создайте следующий пустой файл и папки если их нету:<br />',
    'license_file_not_writable' => '<span style="color:red;">Ошибка</span>: сделайте для записи следующие пути:<br />',
    'invalid_local_key_storage' => '<span style="color:red;">Ошибка</span>: не возможно удалить старый локальный ключ.',
    'could_not_save_local_key' => '<span style="color:red;">Ошибка</span>: не возможно записать новый локальный ключ.',
    'activation_key_string_mismatch' => '<span style="color:red;">Ошибка</span>: локальный ключ не действителен для указанного ключа активации.'

    );

    // Запускаем валидацию лицензии
    $protect->validate();

    $license = false;

    // Если истина, то лицензия в боевом состоянии и можно работать дальше.
    if($protect->status) {
    $license = true;
    }


    Немного доработок в условиях:
    // Если есть ключ и задан ID новости и проверка лицензии прошла успешно — работаем
    if ($cfg['newsId'] && $key && $license) {
    ....
    }
    if (!$key) {
    // Если ключ не передан — надо бы сообщить об этом
    $showAttach = '<span style="color: red;">Не указан лицензионный ключ.</span>';
    }
    if (!$license) {
    // Если лицензия не проверилась - скжем об этом
    $showAttach = (!$protect->errors) ? 'Ошибка лицензии.' : $protect->errors;
    }

    echo $showAttach;


    Если всё сделано правильно — файл с лицензией будет успешно создан в нужной папке, скрипт будет работать., а в админке PCP-CS появится запись о том, где активирован ключ.
    Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE

    Как защитить свой php-скрипт и привязать его к домену на примере модуля для DLE


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


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


В качестве дополнения


Код pcp-cs очень хорошо прокомментирован и для реализации различных вариантов проверки достаточно почитать что там написано. К примеру для использования модуля на локалке без активации достаточно прописать параметр:
$protect->use_localhost = true;

Ну и конечно же если у вас есть идеи и пожелания - мы с Олегом будем всегда рады видеть эти пожелания на гитхабе

Похожие материалы

Комментарии

Ойбек
Ойбек 30 сентября 2016 06:25
Благодарю!
Ойбек
Ойбек 30 сентября 2016 06:48
и ещё, у меня вот такой код существует, который отвечает за ключь
$protect->activation_key = 'xxxx-xxxx-xxxx-xxxx-xxxx';

как сделать, чтобы данное значение xxxx-xxxx-xxx брал он из другого файла, например key.php
xxxx-xxxx-xxxx-xxxx-xxxx

Побывал вот так, что то не получился:
$protect->activation_key = 'include(key.php)';
ПафНутиЙ
ПафНутиЙ 30 сентября 2016 12:21
Ойбек, скрипт расчитан на разработчиков, поэтому вам, как разработчику должны быть известны способы, которыми можно получить содержимое файла.
Для начинающих лучше отказаться от этого скрипта и для начала распространять свои работы бесплатно и с полностью открытым кодом.
Ойбек
Ойбек 30 сентября 2016 13:57
Я ведь начинающий и учусь кое чему...
ПафНутиЙ
ПафНутиЙ 30 сентября 2016 15:38
Начните с изучения языка программирования, на котором собираетесь писать.
buvalii
buvalii 11 октября 2016 14:08
Здравствуйте. Скажите пожалуйста, а как формируется md5 какие параметры он принимает. Спасибо
buvalii
buvalii 11 октября 2016 14:19
{protect}721be5da02d9494e3ca4259b6f307738{protect}e4579401556a4f5213b238d909eacb77 Вот эти ключи каким образом генерируються
ПафНутиЙ
ПафНутиЙ 11 октября 2016 20:41
информацию о работе функции md5 можно найти на php.net

Эти ключи генерируются в коде, вы можете открыть его и посмотреть используемые методы.
buvalii
buvalii 11 октября 2016 20:43
А можете пожалуйста показать код, где именно это происходит. Спасибо.
ПафНутиЙ
ПафНутиЙ 11 октября 2016 20:56
Происходит что?
buvalii
buvalii 11 октября 2016 20:59
Набор строк, где происходит шифрование md5, и какие переменные входят в эту строку, что потом шифруется md5. Спасибо
ПафНутиЙ
ПафНутиЙ 11 октября 2016 21:05
buvalii
buvalii 11 октября 2016 21:17
Спасибо
buvalii
buvalii 14 октября 2016 14:35
Здравствуй. Подскажи по пожалуйста по твоему коду с этой строчкой
if (md5((string)$this->secret_key . (string)$parts[0]) != $parts[1])[code]
[/code]
Каким значениям равно массив $parts, а именно $parts[0] и $parts[1]
ПафНутиЙ
ПафНутиЙ 15 октября 2016 12:57
var_dump($parts[0])
var_dump($parts[1])

Пожалуйста, начните уже читать php.net хотя бы.
midav
midav 6 декабря 2016 20:22
искал много решений которые позволил бы привязывать к домену скрипт. И решил сам написать мини сервис в котором вы сможете создавать продукты и к ним генерировать ключи и раздавать своим клиентам.
Вот картинка API описание. если будет востребователен этот сервис могу его открыть для всех желающих.

Вот картинка описания API как это все работает
API описаниеAPI описание
ПафНутиЙ
ПафНутиЙ 6 декабря 2016 22:00
Проблема всех сервисов в том, что рано или поздно они закроются.
Wild
Wild 8 июня 2017 17:13
Хм, идея интересная.
А есть еще похожие сервисы?
JakimOFF
JakimOFF 4 июля 2017 11:57
Я вот только что зарегистрировался специально что бы поблагодарить. Я уже не первый раз попадаю на Ваши статьи с возможностью решения, и всегда аналогов больше нигде не нахожу да и не приходиться искать. Все отлично расписано, все доступно, все высший класс!
Спасибо!
ПафНутиЙ
ПафНутиЙ 7 июля 2017 06:32
Цитата: Wild
А есть еще похожие сервисы?

Думаю да.

Цитата: JakimOFF
Я вот только что зарегистрировался специально что бы поблагодарить. Я уже не первый раз попадаю на Ваши статьи с возможностью решения, и всегда аналогов больше нигде не нахожу да и не приходиться искать. Все отлично расписано, все доступно, все высший класс!
Спасибо!

Пожалуйста smile

Добавить комментарий

Комментировать могут только зарегистрированные пользователи

Информация

Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.