Вход в систему

Автор Владислав Демьянишин, sulfurzona.com

 

Мастер класс по РНР

Защита контента от копирования: Панацея или утопия?
Теперь домашняя страничка в сети есть у очень многих людей. Такая страничка может быть в ЖЖ, блоге, а может быть и на бесплатном хостинге, или даже на платном.

Многие владельцы авторских сайтов пользуются распространенными движками вроде Joomla или WordPress, но есть и такие, которые самостоятельно изучают азы НТML-языка и ваяют что-то свое с оригинальным дизайном, кодом и содержанием.

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

Но потом первая волна восхищенных посетителей проходит и сама собой приходит необходимость продвижения сайта. Сайт регистрируется во всевозможных поисковиках и каталогах, а может и осторожно светится в тематических форумах.

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

Я не упомянул о платной раскрутке через баннерную сеть и всякие там Adwords’ы, поскольку к этому прибегают уже в случае коммерческой целесообразности.

И вот тут нечистые на руку конкуренты или просто завистники, стремящиеся привлечь интересным контентом к своим проектам побольше посетителей, начинают потихоньку “тырить" оригинальный контент, а то и саму идею проекта.

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

Как раз о способах защиты контента сайта от таких расхитителей мне и хотелось бы сегодня поразмышлять с вами. При этом предполагается, что читатель уже знаком с языками HTML и Javascript.

Но сначала надо набросать макетик нашего экспериментального сайта, на котором мы будем проверять различные методики защиты. Это даже не макет, а просто тестовая веб-страничка в виде HTML-кода, конечно же, с “шапкой” и главным меню сайта в упрощенном виде:

<html><body>

<table width="300” border=”1”>

<tr>

<td colspan="2”><H1 align=”сеnter”>Мой caйт</H1></td>

</tr>

<tr>

<td width-’100” >

<Ь>Меню:</Ь>

<LI><a href=”main.htm”>Главная</a>

<LI><a href=”content.htm”>Cтaтьи</a>

<LI><a href=”contacts.htm”>Koнтaкты</a>

</td>

<tdwidth=”200">

Текст статьи, который защищён от копирования

</td>
</tr>

</table>

</body></html>

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

Но для осмысления наших экспериментов это нам вполне подойдет. Ну и рамку таблицы я сделал видимой, чтобы понятен был “скелет” верстки сайта.

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

Метод 1. Запрет выделения текста

Сначала попробуем защитить статью нашего сайта в виде текста "Текст статьи, который защищен от копирования” от банального выделения, которое предшествует копированию текста прямо из окна браузера. Думаю, читатели сами не раз подобным образом копировали текст какой-нибудь любопытной или полезной статьи, найденной в Интернете.

Как пользователь Интернета, я не раз встречал сайты, где веб-страница составлена таким образом, чтобы препятствовать попытке пользователя выделить текст. Зачастую, это достигается наложением обширного пустого тега DIV поверх плоскости всей или части веб-страницы.

На самом деле этого можно достичь более цивилизованным и простым способом. Давайте в HTML-коде нашего мини-сайта пустой тег BODY заменим следующим кодом с заглушкой обработчика события onselectstart:

<body onselectstart=”return false”>

Такой код успешно защитит наш текст от выделения мышкой в Internet Explorer (IE) и Google Chrome, а вот в FireFox и Opera текст по-прежнему можно выделять. Но и на это есть управа - достаточно лишь в тег BODY добавить описание стиля style=”-moz-user-select: none”, чтобы наш тег получил вид: <body onselectstart=”return false” style=”-moz-user-select: none”>

В итоге Mozilla FireFox уже не позволит выделить текст, но не Opera. В качестве альтернативы этому стилю можно применить заглушку для обработчика события onmousedown, тогда тег BODY будет
иметь уже вид:    

<body onselectstart=”return false” onmouse-down=”return false” >

Впрочем, если это необходимо, можно составить заголовок страницы следующим образом:

<html><head>
<script>
document.onmousedown=function () {return false} </script><head>
<body onselectstart=”return false” >
чтобы добиться такого же результата. Это кому как понравится. Теперь и Opera работает на нас;)

Метод 2. Блокируем контекстное меню

С выделением текста вроде бы разобрались. Но остается проблема, которая заключается в том, что в любом браузере правым кликом мышки можно вызвать контекстное меню, кстати, оно тоже показано на рис. 1.

Но поскольку выделение текста мы уже заблокировали, то на контекстное меню можно было бы не обращать внимания, если бы в нем отсутствовал пункт “Просмотр HTML-кода” (для IE), “Исходный код страницы” (для FireFox), “Просмотр кода страницы" (Chrome), “Исходный код" (Opera).

Более-менее опытному пользователю эта команда позволит просмотреть исходный HTML-код нашей веб-страницы и скопировать из нее текст, что нам, согласитесь, будет весьма неприятно.

Поэтому невольно приходим к выводу, что контекстное меню тоже надо блокировать. Достаточно во все тот же многострадальный тег BODY добавить еще одну заглушку события oncontextmenu: cbody onselectstart=”return false” onmouse-down=”return false” oncontextmenu=”return false”>
Убедитесь сами, что контекстное меню правым кликом мыши не вызывается во всех четырех браузерах. Но вынужден вас огорчить, поскольку команда просмотра исходного кода страницы по-прежнему доступна в том же IE через меню Вид > Просмотр HTML-кода, в FireFox в меню Вид > Исходный код страницы, в Chrome через меню Настройка > Инструменты > Просмотреть исходный код, а в Opera Меню > Страница > Средства разработки > Исходный код.

К тому же пользователь сможет добиться успеха, применив в любом браузере кроме IE и Chrome комбинацию клавиш Ctrl+A, чтобы выделить текст и Ctrl+C, чтобы скопировать его.

Метод 3.Чистим буфер обмена

Продолжая мысль о копировании текста логично предположить, что при копировании текст попадает в буфер обмена. Тем более это можно утверждать наверняка.

Значит, пока пользователь не вставил текст из буфера обмена, этот буфер нужно очистить или даже воспрепятствовать записи в буфер обмена. Для этого составим обработчик события оnсору тега BODY:

<html><head>

<script>

function MyCopy () { if (window.clipboardData) { window.clipboardData.setData (“Text”, "Статья защищена");

}

return false;

}

</script>

</head>

<body oncopy-’return MyCopy ()“>
в котором будем блокировать стандартную обработку копирования и очищать буфер обмена, если он не пустой. В результате получим защиту от копирования текста в IE, FireFox и Chrome, а вот браузер Opera не генерирует данное событие.

Метод 4.Динамическая загрузка контента и слежка за курсором

В большинстве случаев можно решить данную проблему при помощи динамической загрузки контента. Идея заключается в том, чтобы в исходном коде веб-страницы вместо текста статьи был расположен какой-то тег, например, с id=”my_text", внутрь которого и будет производиться загрузка текста статьи по клику на какой-то ссылке.

Такой подход в случае с IE и Opera абсолютно решает проблему защиты от сохранения вебстраницы через меню Файл > Сохранить как и через Вид > Просмотр HTML-кода. При сохранении веб-страницы пользователь получит исходный код, где изначально пустой тег для статьи так и останется пустым.

<html><head>

<script type=”text/javascript” sre=”request.js”x/script>

<script> var mx = 0; var my = 0;
var src_text = function MyMouseMove (x, у) { mx = x; my = y;

}

function BodyEnter () {    я

var d = document.getElementByld (‘my_text’);; if (src_text!=”") d.innerHTML = src_text;

}

function BodyOut () {

if((my<100) || (my>document.body.clientHeight-100)||

(mx<100) || (mx>document.body.clientWidth-100)) {    

var d = document.getElementByld (‘my_text’); src_text = d.innerHTML; d.innerHTML = “&nbsp;”;

function LoadContentComplete (c) { if (c != null) if (c.length>0) { src_text = c;

vard = document.getElementByld (“my_text“); , d.innerHTML = c;

}

}

function LoadContentStart (id) {

request (‘get_content.php?id=’ + id, 0, "LoadContentComplete”);

}

</script><head>

<body onselectstart=”return false” onmouse-down=”return false" oncontextmenu=”return false” , onMouseMove=”javascript: MyMouseMove (event.clientX, event.clienlY) “
onMouseOver=”javascript: BodyEnter () “
onMouseOut=”javascript: BodyOut () “
onMouseOut-’javascript: BodyOut () “>

<table width=”300” border=”1">

<tr>    '

<td colspan=”2”><H1 align"=”сеntег”>Мой caйт</H1></td>

</tr>

<tr>

<td width=”100">

<Ь>Меню:</Ь>

<Ll> href=”main.htm”>Главная</a> <LIXa href-’javascript: LoadContentStart (1) “>Статьи</а>
<Ll> href=”contacts.htm”>KoHTaKTы</a>

</td>

<td width=”200” id=”myjext”>

&nbsp;

</td>

</tr>

</tаble>

</body></html>

Как видно из примера, сначала подключаем модуль request.js для работы с HTTPRequest. Именно через него и будем загружать статьи. Далее идет объявление функций на Javascript, где функция MyMouseMove на входе получает координаты курсора мыши и сохраняет их в переменные mх и mу. Вызов этой функции следует осуществлять именно таким образом, если необходима кросс-браузерная работа.

Функция BodyOut выполняется, когда курсор мыши покидает элемент веб-страницы, но также вызывается, когда курсор покидает окно просмотра веб-страницы в браузере.

Именно для того, чтобы отловить момент, когда курсор мыши покидает именно окно просмотра веб-страницы, эта функция дополнительно проверяет выход курсора за воображаемые рамки и если курсор ушел, то скрывает текст статьи. Функция BodyEnter наоборот, следит за входом курсора в окно просмотра, и восстанавливает отображение статьи.

Функция LoadContentStart по ссылке вызывается для отправки запроса на загрузку статьи через скрипт get_content.php, передавая ему некий идентификатор статьи.

Функция LoadContentComplete выполняется, когда получен ответ от скрипта get_content.php, чтобы отобразить статью.

Для теста составим упрощенный исходный код скрипта get_content.php:

<?

header (‘Content-Type: text/plain; charset=win-dows-1251’);

?>

Текст статьи, который защищён от копирования
Привожу исходный код скрипта request.js для работы HTTPRequest: var r_url = null; var rjimeout = 0; var r_parser = null; var r_request = null; function request_cancel () { rjimeout = 0;

} >

function request_change_url (url) {
r_url = url;    

}

function request_done (c) {
if (r_parser != “”) eval (r_parser + “ (c) “);
if (r_timeout) setTimeout (“request_url (r_url) “, r_timeout);

}

function request_action () { if (r_request.readyState == 4)
request_done (r_request.status == 200 ?
r_request.responseText: null);

}

function request_url (url) {
if (window.XMLHttpRequest) {
r_request = new XMLHttpRequest ();
if (r_request) {

r_request.onreadystatechange = request_action;
r_request.open (“GET”, url, true); r_request.send (null);

}

}

else if (window.ActiveXObject) { rjequest = new ActiveXObject (“Microsoft.XML-HTTP”);

if (r_request) {

r_request.onreadystatechange = request_action;
r_request.open (“GET”, url, true);
r_request.send ();

}

}

}

function request (url, timeout, parser) {
r_url = url;
rjimeout = timeout;
r_parser = parser;

if (rjimeout) setTimeout (“request_url (r_url) r_timeout);
else requestjjrl (r_url);

}

Такая методика была избрана потому, что даже обработка событий document, onfocusout, docu-ment.onfocusin для IE или window.onblur, window.onfocus для прочих браузеров не дает желаемого результата.

Поскольку все эти события происходят уже в момент открытия окна просмотра исходного кода либо диалогового окна сохранения веб-страницы. А это уже очень поздно и скрыть текст статьи не удается.

Но и тут нас ожидает неудача, если пользователь будет пользоваться браузером FireFox
или Chrome. Нет, просмотрев исходник, он уже не увидит нашей статьи, но вот сохранить страницу он сможет и там каким-то непонятным еще для меня образом окажется наша статья, которую мы так стремимся защитить от копирования.

Метод 5. Фрейм в роли сейфа

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

<td width=”200” >

ciframe src=”text.htm” name=”my_frame” id=”my_f rame” ></iframe >

</td>

Составим код страницы text.htm:

<html><head><script>

function SetMyText (s) {

var d d document. getElementByld (‘my_text’);

d.innerHTML = s;

}

</script></head>

<body onselectstart=”return false” onmouse-down=”return false” oncontextmenu-"return false” >
<div id=”my_text”>&nbsp;</div>

</body></html>

И в соответствии с этим перепишем код функции LoadContentComplete основной веб-страницы: function LoadContentComplete (с) { if <с != null) if (c.length>0) { srcjext = c; window.frames [' my frame’].

SetMyText (c);
}
}

В итоге получим абсолютно защищенную статью, если ее будут просматривать в браузерах IE, Chrome и Opera, но, увы-увы-увы, неподдающимся остался FireFox.

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

Но при выборе пункта меню Сохранить как или нажатии комбинации клавиш Ctrl+S появляется диалоговое окно, которое может расположиться как раз над этой заданной областью и скрипт все еще будет получать эти координаты курсора и восстановит текст статьи.

В итоге пользователь сохраняет статью успешно и смеется над нами. Тут решением может быть рас-
положение области просмотра статьи подальше от левого края окна браузера.

Тогда пользователь сможет сохранить статью в браузерах FireFox и Chrome только в том случае, если случайным образом перетащит диалоговое окно сохранения как раз поверх области просмотра статьи и в таком положении диалогового окна сохранит страницу.

Или же если попадется любопытный пользователь, да еще и знающий язык Javascript, срхранит страницу без статьи, проанализирует код скрипта и попытается проделать простую манипуляцию с диалоговым окном сохранения страницы еще раз.

Метод 6. Последняя надежда

Итак, фрейм нам ничем не помог. Моя попытка динамически создавать тег для статьи через команды createElement и appendChild тоже защиты не прибавила. Остается еще раз переписать наш код, выбросив все ненужное.

Динамическая загрузка статей понадобится, поэтому подключение модуля request.js оставляем. Выбрасываем функции BodyEnter, BodyOut - их заменит работающая четче многофункциональная переработанная MyMouseMove и дополнительная к ней функция getBounds. function getBounds (obj) { var left = obj.offsetLeft; var top = obj.offsetTop;

for (var parent = obj.offsetParent; parent; parent = parent.offsetParent) { left += parent.offsetLeft; top += parent.offsetTop;

}

return {left: left, top: top, width: obj.offsetWidth, height: obj.offsetHeight};

}

function MyMouseMove (x, y) { mx = x; my - y;

vaf d*= document.getElementByld (‘my_text’); var bounds = getBounds (d); if ((my>bounds.top) &&

(my<bounds.top+bounds. height) && (mx>bounds.left) && fmx<bounds.left+bounds.width)) {

; W(src_text!=””) SetMyText (srcjext); fffliiif SetMyText (“&nbsp;”);

SB I

Создаем функцию SetMyText:

function SetMyText (s) {

var d P document.getElementByld (‘my_text’);

d.innerHTML = s;

)

упрощаем LoadContentComplete:
if (c.lengthX)) { src_text = c;

SetMyText (c);

}

}

Из BODY выбрасываем ненужное и получаем: ШШГ. onsdlectstart^'Vetum false” onmouse-doWn=return false” oncontextmenu=”return false” onMouseMove=”javascript: MyMouseMove (event.clientX, event.clientY) “>

Возвращаемся к прежнему коду все той же ячейки нашей таблицы:

</td>

<td width=”200” id=”my_text”>

</td>

Только одна очень важная деталь: напоминаю, что ячейка my_text для отображения статьи должна располагаться как можно дальше от левого края окна браузера.

Это обеспечит защиту статьи от нелюбопытных и некомпетентных пользователей. Но получится очень неприятная для пользователя вещь - статья будет видна только при наведении курсора на область ее отображения.

Последние рекомендации

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

Т.е. следует организовать проверку рефералов (это должна быть страница вашего сайта) и интервалов между открытием страниц с одного и того же IP - как вы сами понимаете, пользователь-человек физически не в состоянии открывать несколько страниц в секунду.

Желательно делать ссылки на изображения относительными, а не абсолютными, в этом случае плагиатор не сможет просто взять часть вашего кода и вставить в свой дизайн.

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

Недостаток этого метода в том, что при обмене баннерами принято высылать не сам баннер, а только код ссылки на него. А если запретить загрузку картинок с других доменов, то баннеры отображаться не будут. Поэтому для баннеров рекомендую создать отдельную папку на сервере и установить для нее индивидуальные разрешения.

Также не маловажно прописать в robots.txt ваш host. Часто ищут давно не обновляющиеся сайты и дела-
исковыми системами. Пример: User-agent: *

Host: www. mysite.com В качестве дополнительной меры предлагаю при помощи скрипта вставлять в пустые строки между абзацами так называемые "водяные знаки” в виде текста с цветом фона.

Чтобы плагиатор не мог очистить текст украденной статьи автоматически (например, при помощи своего скрипта), можно генерировать вставки в виде неповторяющегося текста.

Например: “статья с сайта www.mysite.com”, “статья принадлежит сайту www.mysite.com”, “права на статью www.mysite.com”, “права сайта www.mysite.com”,“copyrightwww.mysite.com”, “(с) www.mysite.com” и в таком духе.

Разумеется, для каждой такой вставки следует предусмотреть индивидуальное имя стиля, чтобы снова-таки затруднить автоматику очистки вашей статьи от признаков собственности.

Если уж этот парень украл вашу статью, то пускай работает ручками - бездарь несчастный, или пишет скрипт на регулярных выражениях, если в силах;).

Такой способ заметно сократит темпы сдирания материалов с вашего сайта. Однако не следует забывать о поисковиках, которые должны получать истинное содержание, если вы желаете, чтобы ваш сайт успешно индексировался.

Подводим итоги

Как показали результаты наших экспериментов, нам все же удалось добиться хороших результатов по обеспечению защиты контента, если это касается браузеров IE и Opera. Но что касается FireFox и Chrome, тот туг наша защита получилась однобокой.

Имеются еще несколько приемов, таких, как скрытие панели инструментов и главного меню окна браузера, а также отображение страницы в модальном окне. Но далеко не все браузеры позволяют это делать.

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

В результате сегодняшних размышлений и экспериментов прихожу к выводу, что чуть ли не единственный способ защитить контент абсолютно - это либо применять ActiveX, либо Java- или Flash-npoграммирование.

Либо разрешить доступ к статьям только регистрированным пользователям, что очень распространено в сети. Поэтому хочу дать напутствие: не зацикливайтесь на достигнутом, а изучайте новые технологии.