This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/kohana/modules/userguide/guide/ru-ru/security.validation.md

243 lines
16 KiB
Markdown
Raw Normal View History

2010-08-21 04:43:03 +00:00
# Валидация
С использованием [Validate] класса можно произвести валидацию любого массива. По ключу значения массива ("наименование поля" для валидатора), к объекту валидации можно добавить ярлыки, фильтры, правила и функции обратного вызова.
labels (ярлыки)
: Ярлык - это удобочитаемая интерпретация имени поля.
filters (фильтры)
: Фильтр видоизменяет значение поля перед применением к нему правил и функций обратного вызова.
rules (правила)
: Правило - это проверка значения поля, которая возвращает `TRUE` или `FALSE` в результате проверки. Если правило возвращает `FALSE`, то полю будет добавлена информация об ошибке.
callbacks (функция обратного вызова)
: Функция обратного вызова - это пользовательский метод, который имеет доступ до содержания объекта валидации. Возвращаемое значение функции игнорируется, ввиду этого, функция должна сама добавлять ошибку к полу объекта валидации, используя метод [Validate::error], при возникновении ошибки.
[!!] Заметьте, что функции обратного вызова объекта [Validate] и функции обратного вызова PHP ([PHP callbacks](http://php.net/manual/language.pseudo-types.php#language.types.callback)) - это не одно и то же.
Если вместо имени поля при добавлении фильтра, правила или функции обратного вызова использовать значение `TRUE`, то этот фильтр, правило или функция будет применена ко всем полям объекта Validate.
**В мерах предосторожности, объект [Validate] удалит все поля из массива, которым не присвоен ярлык, фильтр, правило или функция обратного вызова. Это предотвращает доступ до полей, которые не участвуют в валидации.**
Создание объекта валидации производится с использованием метода [Validate::factory]:
$post = Validate::factory($_POST);
[!!] Далее в данном руководстве будет использован объект `$post`. Как пример, будет рассмотрена валидация регистрации нового пользователя.
### Стандартные правила
Класс валидации содержит следующие правила:
Наименование правила | Действие
------------------------- |-------------------------------------------------
[Validate::not_empty] | Значение не должно быть пустым
[Validate::regex] | Проверяется значение на совпадение с регулярным выражением
[Validate::min_length] | Минимальная длина значения (минимальное количество знаков)
[Validate::max_length] | Максимальная длина значения (максимальное количество знаков)
[Validate::exact_length] | Длина значения должна быть равна указанному числу
[Validate::email] | Значение должно представлять собой emal адрес
[Validate::email_domain] | Проверяет существование email домена
[Validate::url] | Значение должно представлять собой URL
[Validate::ip] | Значение должно представлять собой IP адрес
[Validate::phone] | Значение должно представлять собой номер телефона
[Validate::credit_card] | Значение должно представлять собой номер кредитной карты
[Validate::date] | Значение должно представлять собой дату (и время)
[Validate::alpha] | Допустимы только буквенные значения
[Validate::alpha_dash] | Допустимы значения, состоящие из букв и тире
[Validate::alpha_numeric] | Допустимы только буквенные и числовые значения
[Validate::digit] | Значение должно представлять собой целое число
[Validate::decimal] | Значение должно представлять собой число десятичное число или число с плавающей точкой
[Validate::numeric] | Допустимы только цифровые символы
[Validate::range] | Значение должно быть в указанных пределах
[Validate::color] | Значение должно представлять собой правильное значение цвета в HEX
[Validate::matches] | Значение должно совпадать со значением другого поля
[!!] Любой метод [Validate] класса может быть использован как правило валидации без определения полного обратного вызова (callback). Например, добавление `'not_empty'` - то же самое, что и `array('Validate', 'not_empty')`.
## Добавление фильтров
Фильтр валидации задаётся как имя поля, метод или функция (используя синтаксис [PHP callback](http://ru2.php.net/callback)) и массив параметров:
$object->filter($field, $callback, $parameters);
Фильтры изменяют значение поля перед проверкой правилами или функциями обратного вызова.
Для того, чтобы конвертировать значение поля "username" в нижний регистр:
$post->filter('username', 'strtolower');
Если мы хотим удалить все пробелы до и после значения у *всех* полей:
$post->filter(TRUE, 'trim');
## Добавление правил
Все правила валидации задаются как имя поля, метод или функция (используя синтаксис [PHP callback](http://ru2.php.net/callback)) и массива параметров:
$object->rule($field, $callback, $parameters);
Для начала, инициируем валидацию `$_POST` массива, который содержит информацию о регистрации:
$post = Validate::factory($_POST);
Далее, нам необходимо обработать полученные данные, используя [Validate] класс. Во-первых, добавим несколько правил:
$post
->rule('username', 'not_empty')
->rule('username', 'regex', array('/^[a-z_.]++$/iD'))
->rule('password', 'not_empty')
->rule('password', 'min_length', array('6'))
->rule('confirm', 'matches', array('password'))
->rule('use_ssl', 'not_empty');
В виде правила можно использовать практически все функции PHP. Например, можно проверить, верное ли значение ввёл пользователь на SSL вопрос:
$post->rule('use_ssl', 'in_array', array(array('yes', 'no')));
Имейте в виду, что все параметры должны быть в виде массива! Если параметры были не в виде массива, то функция `in_array` была бы вызвана как `in_array($value, 'yes', 'no')`, что привело бы к PHP ошибке.
Пользовательские правила могут быть добавлены, используя синтаксис [PHP callback](http://ru2.php.net/callback):
$post->rule('username', array($model, 'unique_username'));
Метод `$model->unique_username()` определяется следующим образом:
public function unique_username($username)
{
// Проверка на то, имеется ли указанное значение username в БД
return ! DB::select(array(DB::expr('COUNT(username)'), 'total'))
->from('users')
->where('username', '=', $username)
->execute()
->get('total');
}
[!!] Пользовательские правила позволяют производить большое количество дополнительных проверок и могут быть использованы для различных целей множество раз. Зачастую, они создаются как методы модели, однако, если необходимо, могут быть определены в любом классе.
## Добавление функций обратного вызова (callbacks)
Все функции обратного вызова (callback) определяются как имя поля, метод или функция (используя синтаксис [PHP callback](http://ru2.php.net/callback)) и массива параметров:
$object->callback($field, $callback, $parameters);
[!!] До версии kohana 3.0.7, функции обратного вызова не обрабатывали входных параметров, в отличие от фильтров и правил. Если Вы используете старую версию, эти параметры будут проигнорированы.
Пароль пользователя должен быть захэширован, если он прошёл валидацию, поэтому это можно сделать, используя функцию обратного вызова:
$post->callback('password', array($model, 'hash_password'));
Это подразумевает, что метод `$model->hash_password()` будет работать следующим образом:
public function hash_password(Validate $array, $field)
{
if ($array[$field])
{
// Хэшировать пароль, если он присутствует
$array[$field] = sha1($array[$field]);
}
}
# Полный пример
Во-первых, нам понадобится представление ([View]), которое содержит HTML форму и которое будет располагаться в `application/views/user/register.php`:
<?php echo Form::open() ?>
<?php if ($errors): ?>
<p class="message">Были допущены следующие ошибки:</p>
<ul class="errors">
<?php foreach ($errors as $message): ?>
<li><?php echo $message ?></li>
<?php endforeach ?>
<?php endif ?>
<dl>
<dt><?php echo Form::label('username', 'Имя пользователя') ?></dt>
<dd><?php echo Form::input('username', $post['username']) ?></dd>
<dt><?php echo Form::label('password', 'Пароль') ?></dt>
<dd><?php echo Form::password('password') ?></dd>
<dd class="help">Пароль должен быть длиной как минимум в 6 знаков.</dd>
<dt><?php echo Form::label('confirm', 'Подтверждение пароля') ?></dt>
<dd><?php echo Form::password('confirm') ?></dd>
<dt><?php echo Form::label('use_ssl', 'Используете дополнительное шифрование?') ?></dt>
<dd><?php echo Form::select('use_ssl', array('yes' => 'Всегда', 'no' => 'По необходимости'), $post['use_ssl']) ?></dd>
<dd class="help">В целях безопасности, при проведении платежей всегда используется протокол SSL.</dd>
</dl>
<?php echo Form::submit(NULL, 'Создать') ?>
<?php echo Form::close() ?>
[!!] В этом примере повсеместно используется хелпер [Form]. Использование [Form] вместо формирования HTML кода формы вручную, гарантирует корректную обработку входящих данных. Если Вы предпочитаете писать HTML собственноручно, используйте метод [HTML::chars], чтобы обезопасить приложение от введённых пользователем данных.
Во-вторых, нам потребуется контроллер и действие этого контроллера, чтобы произвести регистрацию, которые будут располагаться в файле `application/classes/controller/user.php`:
class Controller_User extends Controller {
public function action_register()
{
$user = Model::factory('user');
$post = Validate::factory($_POST)
->filter(TRUE, 'trim')
->filter('username', 'strtolower')
->rule('username', 'not_empty')
->rule('username', 'regex', array('/^[a-z_.]++$/iD'))
->rule('username', array($user, 'unique_username'))
->rule('password', 'not_empty')
->rule('password', 'min_length', array('6'))
->rule('confirm', 'matches', array('password'))
->rule('use_ssl', 'not_empty')
->rule('use_ssl', 'in_array', array(array('yes', 'no')))
->callback('password', array($user, 'hash_password'));
if ($post->check())
{
// Данные прошли проверку, теперь можно зарегистрировать пользователя
$user->register($post);
// Всегда делайте редирект после успешного POST запроса, чтобы избежать
// повторного ввода информации при обновлении страницы
$this->request->redirect('user/profile');
}
// Валидация не прошла, собираем ошибки
$errors = $post->errors('user');
// Отображаем форму регистрации
$this->request->response = View::factory('user/register')
->bind('post', $post)
->bind('errors', $errors);
}
}
Так же нам потребуется модель пользователя, которую поместим в `application/classes/model/user.php`:
class Model_User extends Model {
public function register($array)
{
// Создание нового пользователя в БД
$id = DB::insert(array_keys($array))
->values($array)
->execute();
// Сохраняем id нового пользователя в cookie
cookie::set('user', $id);
return $id;
}
}
Вот и всё, у нас имеется готовый пример для регистрации пользователя, который правильно проверяет введённые пользователем данные!