Безопасность
11.x
.
Почему это важно?
Конфигурация
Laravel стремится сделать реализацию авторизации максимально простой. Фактически, после установки фреймворка почти всё уже настроено. Настройки хранятся в файле app/config/auth.php
, который содержит несколько хорошо документированных параметров для настройки поведения методов аутентификации.
“Из коробки” приложение Laravel включает в себя модель User
в папке app/models
, которая может использоваться вместе с дефолтным драйвером аутентификации Eloquent. При создании таблицы для данной модели убедитесь, что поле пароля принимает как минимум 60 символов.
Если ваше приложение не использует Eloquent, вы можете использовать драйвер database
, который использует конструктор запросов Laravel.
Примечание: Перед тем как начать, пожалуйста, убедитесь, что таблица
users
(или другая, в которой хранятся пользователи) содержит nullable (с возможностью содержать NULL) столбецremember_token
длиною 100 символов (VARCHAR(100)). Этот столбец испольдуется для хранения токена, когда пользователь при логине ставит галку “запомнить меня”.
Хранение паролей
Класс Hash
содержит методы для безопасного хэширования с помощью Bcrypt.
Хэширование пароля по алгоритму Bcrypt:
$password = Hash::make('secret');
Проверка пароля по хэшу:
if (Hash::check('secret', $hashedPassword))
{
// Пароль подходит
}
Проверка на необходимость перехэширования пароля:
if (Hash::needsRehash($hashed))
{
$hashed = Hash::make('secret');
}
Аутентификация пользователей
Для аутентификации пользователя в вашем приложении вы можете использовать метод Auth::attempt
.
if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
return Redirect::intended('dashboard');
}
Заметьте, что поле email
не обязательно и оно используется только для примера. Вы должны использовать любое поле, которое соответствует имени пользователя в вашей БД. Метод Redirect::intended
отправит пользователя на URL, который он пытался просмотреть до того, как запрос был перехвачен фильтром аутентификации. Также в этом методе можно задать дополнительный URL, куда будет осуществлен переход, если первый URL не доступен.
Когда вызывается метод attempt
, запускается событие auth.attempt
. При успешной авторизации также запускается событие auth.login
.
Проверка авторизации пользователя
Для определения того, авторизован ли пользователь или нет, можно использовать метод check
.
if (Auth::check())
{
// Пользователь уже вошёл в систему
}
Если вы хотите предоставить функциональность типа “запомнить меня”, то вы можете передать true
вторым параметром к методу attempt
, который будет поддерживать авторизацию пользователя без ограничения по времени (пока он вручную не выйдет из системы). В такоем случае у вашей таблицы users
должен быть строковой столбец remember_token
для хранения токена пользователя.
if (Auth::attempt(array('email' => $email, 'password' => $password), true))
{
// Пользователь был запомнен
}
Примечание: если метод attempt
вернул true
, то пользователь успешно вошёл в систему.
Имеет ли пользователь токен "запомнить меня"
Метод viaRemember
позволяет узнать, вошел ли пользователь при помощи фичи “запомнить меня”.
if (Auth::viaRemember())
{
// Пользователь вошел, так как ранее ставил галку "запомнить меня"
}
Авторизация пользователя с использованием условий
Вы также можете передать дополнительные условия для запроса к таблице:
if (Auth::attempt(array('email' => $email, 'password' => $password, 'active' => 1)))
{
// Вход, если пользователь активен, не отключен и существует.
}
Для повышения безопасности после аутентификации фреймворк регенерирует ID сессии пользователя.
Доступ к залогиненному пользователю
Как только пользователь аутентифицирован, вы можете обращаться к модели User
и её свойствам.
$email = Auth::user()->email;
Чтобы получить ID залогиненого пользователя, воспользуйтесь методом id
:
$id = Auth::id();
Для простой аутентификации пользователя по ID используется метод loginUsingId
:
Auth::loginUsingId(1);
Проверка данных для входа без авторизации
Метод validate
позволяет вам проверить данные для входа без осуществления самого входа.
if (Auth::validate($credentials))
{
//
}
Аутентификация пользователя на один запрос
Вы также можете использовать метод once
для авторизации пользователя в системе только для одного запроса. Сессии и cookies не будут использованы.
if (Auth::once($credentials))
{
//
}
Выход пользователя из приложения
Auth::logout();
Ручная авторизация
Если вам нужно войти существующим пользователем, просто передайте его модель в метод login
:
$user = User::find(1);
Auth::login($user);
Это эквивалентно аутентификации пользователя через его данные методом attempt
.
Аутентификация и роутинг
Вы можете использовать Фильтры роутов, чтобы позволишь только залогиненным пользователям обращаться к заданному роуту или группе роутов. Изначально Laravel содержит фильтр auth
, который содержится в файле app/filters.php
.
Защита роута аутентификацией
Route::get('profile', array('before' => 'auth', function()
{
// Доступно только залогиненным пользователям.
}));
Защита от подделки запросов (CSRF)
Laravel предоставляет простой способ защиты вашего приложения от подделки межсайтовых запросов (cross-site request forgeries, CSRF).
Вставка CSRF-ключа в форму
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
Проверка переданного CSRF-ключа
Route::post('register', array('before' => 'csrf', function()
{
return 'Вы передали верный ключ!';
}));
HTTP-аутентификация
HTTP Basic Authentication – простой и быстрый способ аутентификации пользователей вашего приложения без создания дополнительной страницы входа. При HTTP-аутентификации форму для ввода логина и пароля показывает браузер, в виде всплывающего окна.
Для HTTP-аутентификации используйте фильтр auth.basic
:
Защита роута фильтром HTTP-аутентификации
Route::get('profile', array('before' => 'auth.basic', function()
{
// Доступно только залогиненным пользователям.
}));
По умолчанию, фильтр basic
будет использовать поле email
модели объекта при аутентификации. Если вы хотите использовать иное поле, можно передать его имя первым параметром методу basic
в файле app/filters.php
:
Route::filter('auth.basic', function()
{
return Auth::basic('username');
});
Авторизация без запоминания состояния
Вы можете использовать HTTP-авторизацию без установки cookies в сессии, что особенно удобно для аутентификации в API. Для этого зарегистрируйте фильтр, вовращающий результат вызова onceBasic
.
Route::filter('basic.once', function()
{
return Auth::onceBasic();
});
Если вы используете Apache + PHP FastCGI, HTTP-аутентификация не будет работать “из коробки”. Вам нужно добавить следующие строки в свой .htaccess
:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Сброс забытого пароля
Модель и таблица
Восстановление забытого пароля – очень распространенная вещь в веб-приложениях. Чтобы не заставлять вас писать его вновь и вновь, Laravel предоставляет встроенные удобные методы для совершения подобных операций.
Для начала убедитесь, что ваша модель User
реализует (implements) интерфейс Illuminate\Auth\Reminders\RemindableInterface
. Модель User
, которая идет с фреймворком, уже реализует его – она включает в себя Illuminate\Auth\Reminders\RemindableTrait
с методами, которые реализуют этот интерфейс.
Реализация RemindableInterface
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements RemindableInterface {
use RemindableTrait;
}
Создание таблицы токенов сброса пароля
Далее, должна быть создана таблица для хранения токенов запросов сброса пароля. Для создания такой таблицы существует artisan-команда auth:reminders-table
.
php artisan auth:reminders-table
php artisan migrate
Контроллер восстановления пароля
Чтобы автоматически создать контроллер восстановления пароля, воспользуйтесь командой auth:reminders-controller
. В папке controllers
будет создан RemindersController.php
:
php artisan auth:reminders-controller
Созданный контроллер содержит метод getRemind
, который показывает форму для напоминания пароля. Вам надо создать эту форму во вьюхе password.remind
(файл remind.blade.php в папке views/password – см. view). Форма должна отправлять POST c email на метод postRemind
Простейший пример password.remind
:
<form action="{{ action('RemindersController@postRemind') }}" method="POST">
<input type="email" name="email">
<input type="submit" value="Send Reminder">
</form>
Метод postRemind
уже есть в сгенеренном RemindersController.php
. Приняв email
POST-запросом, контроллер отсылает на этот адрес письмо с подтверждением. Если оно отсылается нормально, в сессию во flash-переменную status
заносится сообщение об успешной отправке. Если нет – во flash-переменную error
заносится текст ошибки.
Для модификации собщения, которое уйдет пользователю на почту, вы можете изменить в контроллере вызов Password::remind
на, например, такое:
Password::remind(Input::only('email'), function($message)
{
$message->subject('Password Reminder');
});
Пользователь получит письмо со ссылкой на метод getReset
, с токеном для индентификации пользователя. Этот метод вызывает вьюху password.reset
(файл reset.blade.php
в папке views/password
), в которой должна быть форма для смены пароля, со скрытым полем token
и полями email
, password
, and password_confirmation
, например такая:
<form action="{{ action('RemindersController@postReset') }}" method="POST">
<input type="hidden" name="token" value="{{ $token }}">
<input type="email" name="email">
<input type="password" name="password">
<input type="password" name="password_confirmation">
<input type="submit" value="Reset Password">
</form>
Метод postReset
производит замену паролей в вашем сторадже. По умолчанию считается, что пользователи хранятся в БД, с которой умеет работать Eloquent – ожидается $user, который передается в функцию-замыкание имеет метод save
. Если это не так, измените функцию-замыкание в аргументе Password::reset
в контроллере RemindersController
исходя из вашей архитектуры приложения.
Если смена пароля прошла удачно, пользователь редиректится на главную страницу вашего приложения (вы можете изменить URL редиректа, если хотите). Если нет – пользователь редиректится обратно с установкой flash-переменной error
.
Валидация паролей
По умолчанию Password::reset
валидирует пароль пользователя исходя из двух правил – введенные пароли должны совпадать и пароль должен быть больше или равен 6 символам. Если вы хотите расширить валидацию паролей, вы можете определить свой Password::validator
:
Password::validator(function($credentials)
{
return strlen($credentials['password']) >= 6;
});
Токены сброса пароля валидны в течении одного часа. Вы можете изменить это в
app/config/auth.php
, параметрreminder.expire
.
Шифрование
Laravel предоставляет функции устойчивого шифрования по алгоритму AES с помощью расширения mcrypt
для PHP.
Шифрование строки
$encrypted = Crypt::encrypt('секрет');
Примечание: обязательно установите 16, 24 или 32-значный ключ
key
в файлеapp/config/app.php
. Если этого не сделать, зашифрованные строки не будут достаточно надежными.
Расшифровка строки
$decrypted = Crypt::decrypt($encryptedValue);
Изменение режима и алгоритма шифрования
Вы также можете установить свой алгоритм и режим шифрования:
Crypt::setMode('ctr');
Crypt::setCipher($cipher);
Драйвера аутентификации
Laravel из коробки предлагает для аутентификации драйвера database
и eloquent
. Чтобы узнать больше о том, как добавлять свои драйвера, изучите документацию по расширению системы аутентификации.