|
Pers.narod.ru. Javascript. Javascript для проверки данных на стороне клиента - можно ли так делать? |
В инете встречается много странных вопросов и ответов на тему взаимодействия клиентских и серверных скриптов. Мне кажется, достаточно придерживаться спецификаций и чётко понимать разницу между серверным и клиентским приложением.
Когда мы из скрипта на PHP пишем код Javascript оператором print или echo, мы просто выводим его в браузер, точно так же, как обычный HTML. "Передать значение из PHP в Javascript" можно только в этом смысле:
print '<script type="text/javascript">var i='.$i.';</script>';
Здесь переменная яваскрипта i получила значение $i переменной серверного сценария. В дальнейшем яваскрипт может использовать или поменять его, но не передать обратно!
Из Javascript в PHP тем более ничего передать нельзя, ведь Javascript полностью выполняется браузером на стороне клиента (серверные расширения, всякие AJAX и JSQuery здесь не рассматриваем).
Одна из наиболее распространённых проблем - функционал сайта, существенно зависящий от включенного Javascript (например, если проверка данных, введённых пользователем в форму, выполняется только яваскриптом, пользователь чуть похитрее просто отключит яваскрипт и отправит всё, что пожелает). Включение альтернативного содержимого в тег <noscript>, выполняемый только тогда, когда Javascript отключён, помогает не всегда. Даже в том случае, если форма при отключённом скрипте просто не выводится. Что мешает, например, загрузить при включённом Javascript полную версию страницы, а затем, отключив его, обойти встроенные проверки?
Значит ли это, что проверки яваскриптами вообще не нужно делать, а весь ввод обрабатывать только на сервере? В идеале так и есть, но часто хочется упростить серверный сценарий и разгрузить сервер от дополнительных транзакций. Вот пример распространённого подхода, сохраняющего, однако, те недостатки, о которых сказано выше.
В коде на PHP после тела яваскрипта, особенно если он критичен для функционала сайта, помещается тег <noscript>, куда можно поместить содержимое, выводимое при отключённом яваскрипте.
print '<script type="text/javascript">var i=1;</script>
<noscript>
<p>Для работы этой функции нужен включённый в Вашем браузере Javascript.
<a href="help.html">Как включить Javascript?</a></p></noscript>';
Подобный код будет нормально работать на "верхнем" уровне кода PHP, вне всех функций, но в функцию выносить его не стоит.
Теперь посмотрим на следующую форму HTML:
<form method="post" name="f1" action="script.php">
<table border="0" width="90%" align="center">
<tr>
<td>Ваше имя:</td>
<td><input type="text" name="author" size="20" maxlength="40" value=""></td>
</tr>
<tr>
<td>Сообщение:</td>
<td><textarea name="message" rows="10" cols="72"
onchange="document.f1.add.disabled=false;"></textarea>
</td>
</tr>
<tr>
<td> </td>
<td><input type=submit name=add class=button value="Отправить"
disabled onclick="return check();">
</td>
</tr>
</table>
</form>
Представленная схема позволяет, во-первых, по умолчанию отключить активность кнопки отправки (стандартный атрибут disabled), во-вторых, перед отправкой выполняется функция на Javascript с именем check, которая
вернёт истину, если данные правильны, и ложь в противном случае. В простейшем случае функция может быть такой:
<script type="text/javascript">
function checkmail () {
var r=true;
var author=trim(document.f1.author.value);
var message=trim(document.f1.message.value);
if ((author=='') || (message=='')) r=false;
if (r==false) window.alert ('Пожалуйста, заполните оба поля данных.');
return r;
}
</script>
Если Javascript включён, кнопка отправки будет активирована после выхода фокуса
из поля ввода текста message (конечно, этот "выход" фокуса должен быть не на кнопку отправки, а на поле для ввода капчи), в противном случае этого не произойдёт вовсе. Нужно понимать, что если не включать в код атрибут disabled для кнопки отправки и активацию кнопки через Javascript, обойти все наши Javascript-проверки будет элементарно - просто отключив поддержку яваскрипта в браузере! Разумеется, неплохо защитить скрипт на PHP и
проверкой того, с какого URL поступают данные, чтобы отсечь возможность обойти нашу
"защиту" созданием альтеративной формы где-нибудь на сервере "хакера":
define ("MY_SERVER","www.vasya.ru");
//...
list ($formurl,$formparams) = split ('\?',$_SERVER['HTTP_REFERER']);
$formparts = split ('/',$formurl);
if ($formparts[2]!==MY_SERVER) {
//Вывести сообщение об ошибке вида
//"Сообщение отправлено не с моего сервера, а с ".$formparts[2]."!"
}
"Защита", конечно, только от спамера и ламера :) Как и другие данные изначально открытого протокола HTTP, свойство
$_SERVER['HTTP_REFERER'] нетрудно подделать, было бы желание. Но я и не знаю способа стопроцентной защиты от спама, обычно достаточно отсечь хотя бы большую его часть.
Ну и заметим, что на 2-5% пользователей (статистические данные по многим сайтам), отключающих яваскрипт или пользующихся браузером без его поддержки, мы, при таком подходе, просто "забиваем". Альтернатива - писать трудоёмкие noscript-версии сайтов.
|
|