Защита PHP скрипта путям привязки к доменному имени

от автора

Думаю, многие сталкивались с тем, что иногда необходимо защитить ваш скрипт от копирования, и вы использовали разные Ioncube, PHPLockit, но многим неудобно каждый раз кодировать. Понимаю, что в Ioncube есть такая штука, благодаря которой можно генерировать ключи безопасности и т.д., но многим невыгодно покупать или же пользоваться чужими услугами, а то мало ли, все бывает.

Некоторым хочется кодировать не весь код, а лишь его часть, и для этого многие используют такой «массив» для защиты:

$_SERVER['HTTP_HOST'] 

Но его легко обойти:

$_SERVER['HTTP_HOST']='разрешенный домен'; 

Поэтому есть решение данной проблемы, и её может решить любой человек с начальным знанием PHP, MySQL.

В итоге у нас получится:

  • Скрипт будет закодирован путем обфускатора, который посылает API запрос к сайту, где API ищет доменное имя и ключ в базе данных; если он есть, то скрипт будет работать, если нет, то он будет переадресовывать основному сайту (пример будет таким: domain.com/api.php?domain=mysite1.ru&key=4024B-C0876-4FF0C-9A298-80EFA);
  • Также у нас будет скрипт api.php, который будет отвечать за работу проверки лицензии и т.д.;
  • Также хочу выделить лицензионный ключ, который мы будем получать. Лицензионный ключ — это md5 хэш домена, который будет проверятся через api, а в базе данных будет записан лишь сам домен и его статус.

Решение

1. Выдача лицензий и проверка действительности скрипта через api:

<?php  $config = array(  	'host' => 'localhost', 	'user' => 'root', 	'pass' => '', 	'base' => 'lic' 	 );  $db = new mysqli($config['host'], $config['user'], $config['pass'], $config['base']); if($db->connect_errno) {     exit('Ошибка: Не удалось подключиться к базе данных!'); } $db->set_charset("utf8");  class Main { 	public 	function keygen($domain){ 		$key[0] = strtoupper(md5($domain)); 		$key[1] = substr($key[0], 0, 5); 		$key[2] = substr($key[0], 5, 5); 		$key[3] = substr($key[0], 10, 5); 		$key[4] = substr($key[0], 15, 5); 		$key[5] = substr($key[0], 20, 5); 		 		return $key[1].'-'.$key[2].'-'.$key[3].'-'.$key[4].'-'.$key[5]; 	}  	public function getLicInfo($domain){ 		global $db, $config; 		 		$sql = "SELECT * FROM `licenses` WHERE `domain` = '{$domain}' LIMIT 1"; 		$result = $db->query($sql);  		if($result->num_rows == 1){ 			return $result->fetch_assoc(); 		} 		return false; 	} }  $main = new Main;  $domain = "".$_GET['domain'].""; $key = strtoupper($_GET['key']);    if($lic = $main->getLicInfo($domain)){ 	if($lic['license_status']){ 		$twokey = $main->keygen($lic['license_domain']); 		if($twokey == $key){ 			$a = 'OK_'.$lic['license_domain']; 		} else { 			$a = 'ERROR_wrongkey'; 		} 	} else { 		$a = 'ERROR_nolicense'; 	} } else { 	$a = 'ERROR_nolicense'; }  echo $a; exit(); ?> 

Вот сам код api.php. Тут я хотел бы обратить ваше внимание на следующий код:

class Main { 	public 	function keygen($domain){ 		$key[0] = strtoupper(md5($domain)); 		$key[1] = substr($key[0], 0, 5); 		$key[2] = substr($key[0], 5, 5); 		$key[3] = substr($key[0], 10, 5); 		$key[4] = substr($key[0], 15, 5); 		$key[5] = substr($key[0], 20, 5); 		 		return $key[1].'-'.$key[2].'-'.$key[3].'-'.$key[4].'-'.$key[5]; 	} 

Данный класс создает ключ домена путем использования md5 хэш.

2.Проверка доменного имена на наличие в базе данных
В 1 пункте мы с вами обозревали код api.php, который отвечает за работу скрипта. Хочу выделить код, который я уже выделял:

	public function getLicInfo($domain){ 		global $db, $config; 		 		$sql = "SELECT * FROM `licenses` WHERE `domain` = '{$domain}' LIMIT 1"; 		$result = $db->query($sql);  		if($result->num_rows == 1){ 			return $result->fetch_assoc(); 		} 		return false; 	} } 

Данный класс проверяет доменное имя на наличие в базе данных, и если все удачно, то скрипт работает; если нет, то он переадресует на основной сайт.

Вот мы с вами закончили обозревать код api.php, который отвечает за основную работу проверки лицензии, но теперь стоит вопрос: «А как его реализовать в самом скрипте?»

Делается оно благодаря следующему коду:

	public function __destruct() { 		$request = file_get_contents("http://domain.com/api.php?domain=". $_SERVER['HTTP_HOST'] ."&key=".$this->config->lic_key); 		$status = explode("_", $request); 		 		if($status[0] != "OK" && "".$_SERVER['HTTP_HOST']."" != $status[1]){ 			header("Location: http://domain.com/"); 		} 	} 

Этот код отправляет запрос в API и если имеется в базе данных, и если доменное имя есть в базе данных, то скрипт работает, если нет, то не работает. Такая же ситуация, если код неправильный, для этого в api.php существует следующий «отрезок» кода:

if($lic = $main->getLicInfo($domain)){ 	if($lic['license_status']){ 		$twokey = $main->keygen($lic['license_domain']); 		if($twokey == $key){ 			$a = 'OK_'.$lic['license_domain']; 		} else { 			$a = 'ERROR_wrongkey'; 		} 	} else { 		$a = 'ERROR_nolicense'; 	} } else { 	$a = 'ERROR_nolicense'; }  echo $a; exit(); 

Думаю, тут понятно: если все правильно, то «выходит» сообщение ok_myssite.com и это удовлетворяет, то скрипт продолжает работу, а если введен неверный ключ или доменное имя, то «выходит» следующие сообщения (смотря где есть ошибка):

ERROR_nolicense

или же

ERROR_wrongkey

Думаю, все. Также жду конструктивных комментариев, и благодарю pixxxel за его статью «Защита PHP скриптов от копирования — это возможно?»

ссылка на оригинал статьи http://habrahabr.ru/post/263075/


Комментарии

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

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