Работая над написанием административного, да и пользовательского интерфейса, я не раз ловил себя на мысли — а все ли я делаю так, чтобы при минимуме усилий обеспечить оптимальное качество?
Сегодня хотелось бы обсудить вопрос обработки ошибок ввода форм в веб-приложениях. Как, вы все еще всецело доверяете вводимым пользователем данным и считаете сидящее по ту сторону монитора существо священной коровой? Не бойтесь, это пройдет после первой же атаки, если принципы контроля ввода не станут вам ясны раньше. Впрочем, к делу.
Программирую я на PHP, поэтому примеры серверного кода будут на этом языке.
Представим, что мы решили дополнить свой проект формой для заказа обратного звонка. Мало ли — линии часто перегружены, клиент хочет почувствовать свою весомость, мода такая… ну в общем надо. Быстро накидываем простейший html, пишем обработчик — данные красиво легли в базу, в общем — практически готово. Осталось сделать самую малость — написать обработку ошибок. (Конечно, порядок разработки весьма условен). Каким образом можно это проверить введенную пользователем информацию на правильность и уведомить его о результате?
В случае с правильно заполненной формой работы минимум. А вот если пользователь допустил ошибку и данные некорректны, вы вынуждены снова сгенерировать страницу и отправить ее пользователю. При этом крайне желательно значения всех заполненных полей сохранить, что увеличивает ваш код.
Рассмотрим базовую обработку ошибок (считаем что пользовательские данные уже прошли основные проверки и фильтрации):
Нам хочется привнести некоторые удобства для клиента. И на помощь нам приходит…
Функция alert использована лишь в качестве учебного примера, по статистике часть пользователей закроет его не читая, потому что выводится оно в дизайне ОС и не воспринимается как часть веб-страницы.
Еще раз обращу внимание на то, что серверная проверка все равно необходима.
Каждый раз, когда меня просят рассказать зачем это нужно, я вспоминаю примерно год 2004, когда я, начинающий веб-разработчик, познакомился по переписке со славным парнем с Украины, бывшим тогда автором собственной CMS. Пытаясь перенимать опыт, я как-то поинтересовался у него, как он производит обработку ошибок. Выяснилось, что делает он это только при помощи JavaScript. Пришлось уже самому делиться опытом о том, что можно сохранить страницу на компьютер, подменить адрес обработчика формы и отправить данные без валидации. И если валидации не будет уже на сервере, некорректные данные будут восприняты как нормальные, а дальше все будет зависеть от логики приложения. Позже в процессе работы я часто встречал подобные уязвимости. Вывод напрашивается сам собой — если веб-приложение пишется без понимания особенностей взаимодействия браузера клиента и сервера, результат может быть разным.
Проходит время, сложность форм растет и я обращаю свой взор на следующую технологию.
Теперь проверка для удобства вынесена в отдельный метод и немного дополнена, в результате получаем примерно такой код:
Далее в браузере клиента мы можем показать тот же самый алерт или вывести сообщение любым другим удобным для нас способом. Юзабилити на высоте — не требуется перезагрузка страницы, удобство дальнейшей поддержки кода тоже — вся обработка ошибок собрана в одном месте.
Пока форма состоит из небольшого количества полей, не так сложно при добавлении очередного поля модифицировать вывод после приема ошибочных данных. А если данных много? В этом случае есть желание облегчить себе работу и отказаться от такой полной поддержки старых браузеров, убрав вывод данных и получив вот такой код:
Мы существенно упростили себе работу по дальнейшей поддержке кода, при этом сознательно отказавшись от полной поддержки устройств с отключенным JavaScript. Чем-то пришлось жертвовать в угоду собственному удобству. Но такой подход не оправдан, если упор идет на качество разработки.
На данный момент я продолжаю экспериментировать с проверками данных. Все еще ищу идеальное решение, которое было бы еще более оптимальным. С удовольствием выслушаю критику и обсужу все аспекты различных подходов с читателями.
Сегодня хотелось бы обсудить вопрос обработки ошибок ввода форм в веб-приложениях. Как, вы все еще всецело доверяете вводимым пользователем данным и считаете сидящее по ту сторону монитора существо священной коровой? Не бойтесь, это пройдет после первой же атаки, если принципы контроля ввода не станут вам ясны раньше. Впрочем, к делу.
Программирую я на PHP, поэтому примеры серверного кода будут на этом языке.
Представим, что мы решили дополнить свой проект формой для заказа обратного звонка. Мало ли — линии часто перегружены, клиент хочет почувствовать свою весомость, мода такая… ну в общем надо. Быстро накидываем простейший html, пишем обработчик — данные красиво легли в базу, в общем — практически готово. Осталось сделать самую малость — написать обработку ошибок. (Конечно, порядок разработки весьма условен). Каким образом можно это проверить введенную пользователем информацию на правильность и уведомить его о результате?
В случае с правильно заполненной формой работы минимум. А вот если пользователь допустил ошибку и данные некорректны, вы вынуждены снова сгенерировать страницу и отправить ее пользователю. При этом крайне желательно значения всех заполненных полей сохранить, что увеличивает ваш код.
Рассмотрим базовую обработку ошибок (считаем что пользовательские данные уже прошли основные проверки и фильтрации):
<?php
$errors = array();
if ( empty($person) || empty($phone) || empty($question) )
{
$errors[] = 'Не заполнены обязательные поля';
}
if ( count($errors) )
{
$template->assign_switch('errors', 1);
$template->vars(array(
'ERRORS' => implode(' ', $errors),
'PERSON' => $person,
'PHONE' => $phone,
'QUESTION' => $question
)
);
$template->send();
}
?>
Нам хочется привнести некоторые удобства для клиента. И на помощь нам приходит…
JavaScript
<script language="text/javascript">
<!-- //
function form_submit()
{
if (
( document.forms['callback'].person.value == '' ) ||
( document.forms['callback'].phone.value == '' ) ||
( document.forms['callback'].question.value == '' )
)
{
alert('Не заполнены обязательные поля');
}
return;
}
// -->
</script>
Функция alert использована лишь в качестве учебного примера, по статистике часть пользователей закроет его не читая, потому что выводится оно в дизайне ОС и не воспринимается как часть веб-страницы.
Еще раз обращу внимание на то, что серверная проверка все равно необходима.
Каждый раз, когда меня просят рассказать зачем это нужно, я вспоминаю примерно год 2004, когда я, начинающий веб-разработчик, познакомился по переписке со славным парнем с Украины, бывшим тогда автором собственной CMS. Пытаясь перенимать опыт, я как-то поинтересовался у него, как он производит обработку ошибок. Выяснилось, что делает он это только при помощи JavaScript. Пришлось уже самому делиться опытом о том, что можно сохранить страницу на компьютер, подменить адрес обработчика формы и отправить данные без валидации. И если валидации не будет уже на сервере, некорректные данные будут восприняты как нормальные, а дальше все будет зависеть от логики приложения. Позже в процессе работы я часто встречал подобные уязвимости. Вывод напрашивается сам собой — если веб-приложение пишется без понимания особенностей взаимодействия браузера клиента и сервера, результат может быть разным.
Проходит время, сложность форм растет и я обращаю свой взор на следующую технологию.
AJAX
Теперь проверка для удобства вынесена в отдельный метод и немного дополнена, в результате получаем примерно такой код:
<?php
$errors = array();
if ( empty($person) || empty($phone) || empty($question) )
{
$errors[] = 'Не заполнены обязательные поля';
}
$ajax = isset($_REQUEST['ajax']);
if ( count($errors) )
{
if ( empty($ajax) )
{
$template->assign_switch('errors', 1);
$template->vars(array(
'ERRORS' => implode(' ', $errors),
'PERSON' => $person,
'PHONE' => $phone,
'QUESTION' => $question
)
);
$template->send();
}
else
{
$ajax_handler->send(array(
'errors' => 1,
'error_text' => implode(' ', $errors),
)
);
}
}
else
{
$ajax_handler->send(array(
'errors' => 0,
'error_text' => '',
)
);
}
?>
Далее в браузере клиента мы можем показать тот же самый алерт или вывести сообщение любым другим удобным для нас способом. Юзабилити на высоте — не требуется перезагрузка страницы, удобство дальнейшей поддержки кода тоже — вся обработка ошибок собрана в одном месте.
Вредный совет
Пока форма состоит из небольшого количества полей, не так сложно при добавлении очередного поля модифицировать вывод после приема ошибочных данных. А если данных много? В этом случае есть желание облегчить себе работу и отказаться от такой полной поддержки старых браузеров, убрав вывод данных и получив вот такой код:
<?php
if ( count($errors) )
{
if ( empty($ajax) )
{
header('Location: form.php?error_code=1');
exit();
}
}
?>
Мы существенно упростили себе работу по дальнейшей поддержке кода, при этом сознательно отказавшись от полной поддержки устройств с отключенным JavaScript. Чем-то пришлось жертвовать в угоду собственному удобству. Но такой подход не оправдан, если упор идет на качество разработки.
Заключение
На данный момент я продолжаю экспериментировать с проверками данных. Все еще ищу идеальное решение, которое было бы еще более оптимальным. С удовольствием выслушаю критику и обсужу все аспекты различных подходов с читателями.