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
2011-05-03 09:49:01 +10:00

243 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Валидация
С использованием [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;
}
}
Вот и всё, у нас имеется готовый пример для регистрации пользователя, который правильно проверяет введённые пользователем данные!