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

16 KiB
Raw Blame History

Валидация

С использованием [Validate] класса можно произвести валидацию любого массива. По ключу значения массива ("наименование поля" для валидатора), к объекту валидации можно добавить ярлыки, фильтры, правила и функции обратного вызова.

labels (ярлыки)
Ярлык - это удобочитаемая интерпретация имени поля.
filters (фильтры)
Фильтр видоизменяет значение поля перед применением к нему правил и функций обратного вызова.
rules (правила)
Правило - это проверка значения поля, которая возвращает TRUE или FALSE в результате проверки. Если правило возвращает FALSE, то полю будет добавлена информация об ошибке.
callbacks (функция обратного вызова)
Функция обратного вызова - это пользовательский метод, который имеет доступ до содержания объекта валидации. Возвращаемое значение функции игнорируется, ввиду этого, функция должна сама добавлять ошибку к полу объекта валидации, используя метод [Validate::error], при возникновении ошибки.

[!!] Заметьте, что функции обратного вызова объекта [Validate] и функции обратного вызова PHP (PHP callbacks) - это не одно и то же.

Если вместо имени поля при добавлении фильтра, правила или функции обратного вызова использовать значение 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) и массив параметров:

$object->filter($field, $callback, $parameters);

Фильтры изменяют значение поля перед проверкой правилами или функциями обратного вызова.

Для того, чтобы конвертировать значение поля "username" в нижний регистр:

$post->filter('username', 'strtolower');

Если мы хотим удалить все пробелы до и после значения у всех полей:

$post->filter(TRUE, 'trim');

Добавление правил

Все правила валидации задаются как имя поля, метод или функция (используя синтаксис PHP 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:

$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) и массива параметров:

$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;
    }

}

Вот и всё, у нас имеется готовый пример для регистрации пользователя, который правильно проверяет введённые пользователем данные!