Может войдёшь?
Черновики Написать статью Профиль

Безопасность

перевод документация 4.x

  1. 1. Настройка
  2. 2. Хранение паролей
  3. 3. Авторизация пользователей
  4. 4. Ручная авторизация
  5. 5. Защита маршрутов
  6. 6. Защита от подделки запросов (CSRF)
  7. 7. Простая HTTP-авторизация
  8. 8. Сброс и изменение паролей
    1. 8.1. Модель и таблица
    2. 8.2. Контроллер сброса паролей
    3. 8.3. Проверка пароля
    4. 8.4. Сброс пароля (4.0)
  9. 9. Шифрование
  10. 10. Драйверы авторизации
Этот перевод актуален для англоязычной документации на (ветка 4.2) , (ветка 4.1) и (ветка 4.0). Опечатка? Выдели и нажми Ctrl+Enter.

Настройка

Laravel стремится сделать реализацию авторизации максимально простой. Фактически, почти всё уже настроено после установки. Настройки хранятся в файле app/config/auth.php, который содержит несколько хорошо документированных параметров для настройки поведения методов авторизации.

По умолчанию Laravel включает в себя модель PHPUser в папке app/models, которая может использоваться вместе с драйвером авторизации Eloquent (по умолчанию). При создании таблицы для данной модели убедитесь, что поле пароля принимает как минимум 0 символов.

Если ваше приложение не использует Eloquent, вы можете использовать драйвер database, который использует конструктор запросов Laravel.

Прежде чем начать, убедитесь, что в вашей таблице users (или её эквиваленте) есть обнуляемое строковое поле на 100 символов. В этом поле будет храниться ключ для сессий «запомнить меня», поддерживаемых вашим приложением. Это можно сделать с помощью PHP$table->rememberToken(); в миграции.

Хранение паролей

Класс PHPHash содержит методы для безопасного хэширования с помощью Bcrypt.

Хэширование пароля по алгоритму Bcrypt

PHP
$password Hash::make('secret');

Проверка пароля по хэшу

PHP
if (Hash::check('secret'$hashedPassword)) {
  
// Пароль подходит...
}

Проверка на необходимость перехэширования пароля

PHP
if (Hash::needsRehash($hashed)) {
  
$hashed Hash::make('secret');
}

Авторизация пользователей

Для авторизации пользователя в вашем приложении используется метод PHPAuth::attempt():

PHP
if (Auth::attempt(array('email' => $email'password' => $password))) {
  return 
Redirect::intended('dashboard');
}

Заметьте, что поле email не обязательно и оно используется только для примера. Вы должны использовать любое поле, которое соответствует имени пользователя в вашей БД. Метод PHPRedirect::intended() отправит пользователя на URL, который он пытался просмотреть до того, как запрос был перехвачен фильтром авторизации. Дополнительный URL может быть передан в метод, если требуемый адрес не доступен.

Когда вызывается метод PHPAuth::attempt() возбуждается событие auth.attempt. При успешной авторизации также произойдёт событие auth.login.

Проверка авторизации пользователя

Для определения того, авторизован ли пользователь или нет, можно использовать метод PHPAuth::check():

PHP
if (Auth::check()) {
  
// Пользователь уже вошёл в систему...
}

Авторизация и запоминание пользователя

Если вы хотите предоставить функциональность типа «запомнить меня», то вы можете передать PHPtrue вторым параметром к методу PHPAuth::attempt(), который будет поддерживать авторизацию пользователя без ограничения по времени (пока он вручную не выйдет из системы). Разумеется, ваша таблица users должна содержать строковое поле remember_token для хранения ключа сессий «запомнить меня».

PHP
if (Auth::attempt(array('email' => $email'password' => $password), true)) {
  
// Пользователь был запомнен...
}

Внимание: если метод PHPAuth::attempt() вернул PHPtrue, то пользователь успешно вошёл в систему.

+ 4.1

добавлено в 4.1 ()

Авторизован ли пользователь через запоминание?

Если вы «запоминаете» входы пользователей, то можете использовать метод PHPviaRemember() для определения того, был ли пользователь авторизован с использованием cookie «запомнить меня»:

PHP
if (Auth::viaRemember())
{
  
//
}

Авторизация пользователя с условиями

Вы также можете передать дополнительные условия для запроса к таблице:

PHP
if (Auth::attempt(array('email' => $email'password' => $password'active' => 1))) {
  
// Вход, если пользователь активен, не отключен и существует.
}

Для дополнительной защиты от фиксации сессии, ID сессии пользователя будет автоматически сгенерирован заново после авторизации.

Доступ к авторизованному пользователю

Как только пользователь авторизован вы можете обращаться к модели PHPUser и её свойствам:

PHP
$email Auth::user()->email;
+ 4.2

добавлено в 4.2 ()

Для получения ID авторизованного пользователя используйте метод PHPid():

PHP
$id Auth::id();

Для простой авторизации пользователя по ID используется метод PHPloginUsingId():

PHP
Auth::loginUsingId(1);

Проверка данных для входа без авторизации

Метод PHPvalidate() позволяет вам проверить данные для входа без осуществления самого входа:

PHP
if (Auth::validate($credentials)) {
  
//
}

Авторизация пользователя на один запрос

Вы также можете использовать метод PHPonce() для авторизации пользователя в системе только для одного запроса. Сессии и cookies не будут использованы.

PHP
if (Auth::once($credentials)) {
  
//
}

Выход пользователя из системы

PHP
Auth::logout();

Ручная авторизация

Если вам нужно авторизовать существующего пользователя просто передайте его модель в метод PHPAuth::login():

PHP
$user User::find(1);

Auth::login($user);

Это эквивалентно авторизации пользователя через его данные методом PHPAuth::attempt().

Защита маршрутов

Вы можете использовать Фильтры маршрутов, чтобы позволить только авторизованным пользователям обращаться к данному маршруту. Изначально Laravel содержит фильтр auth, который содержится в файле app/filters.php.

Защита маршрута

PHP
Route::get('profile', array('before' => 'auth', function () {
  
// Доступно только авторизованным пользователям...
}));

Защита от подделки запросов (CSRF)

Laravel предоставляет простой способ защиты вашего приложения от подделки межсайтовых запросов (CSRF).

Вставка CSRF-ключа в форму

<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

Проверка переданного CSRF-ключа

PHP
Route::post('register', array('before' => 'csrf', function() {
  return 
'Вы передали верный ключ!';
}));

Простая HTTP-авторизация

HTTP Basic Authentication — простой и быстрый способ авторизовать пользователей вашего приложения без создания дополнительной страницы входа. Для начала подключите фильтр auth.basic.

Защита маршрута фильтром HTTP-авторизации

PHP
Route::get('profile', array('before' => 'auth.basic', function () {
  
// Доступно только авторизованным пользователям...
}));

По умолчанию, фильтр basic будет использовать поле PHP$email модели объекта при авторизации. Если вы хотите использовать иное поле, можно передать его имя первым параметром методу PHPbasic() в вашем файле app/filters.php:

PHP
Route::filter('auth.basic', function()
{
  return 
Auth::basic('username');
});

Авторизация без запоминания состояния

Вы можете использовать HTTP-авторизацию без установки cookie в сессии, что особенно удобно для авторизации в API. Для того, чтобы сделать это, зарегистрируйте фильтр, возвращающий результат вызова PHPAuth::onceBasic():

PHP
Route::filter('basic.once', function () {
  return 
Auth::onceBasic();
});

Если вы используете PHP FastCGI, то по умолчанию простая HTTP-аутентификация не будет работать правильно. В файл .htaccess надо добавить следующие строки:

PHP
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Сброс и изменение паролей

Модель и таблица

Большая часть приложений позволяют пользователям сбрасывать свои забытые пароли. Вместо того, чтобы заставлять вас реализовывать эту функциональность в каждом приложении, Laravel предоставляет удобный способ для отправки писем о сбросе пароля и выполнения самого сброса. Для начала убедитесь, что модель PHPUser реализует интерфейс PHPIlluminate\Auth\Reminders\RemindableInterface. Это уже сделано для модели PHPUser, включённой в фреймворк по умолчанию.

В Laravel 4.2 эта модель использует PHPIlluminate\Auth\Reminders\RemindableTrait для включения методов, необходимых для реализации интерфейса. — прим. пер.

Реализация интерфейса PHPRemindableInterface

+ 4.2

добавлено в 4.2 ()

PHP
use Illuminate\Auth\Reminders\RemindableTrait;
use 
Illuminate\Auth\Reminders\RemindableInterface;

class 
User extends Eloquent implements RemindableInterface {

  use 
RemindableTrait;

}
+ 4.1

добавлено в 4.1 ()

PHP
class User extends Eloquent implements RemindableInterface {

  public function 
getReminderEmail()
  {
      return 
$this->email;
  }

}

Генерация миграции для таблиц сброса паролей

Затем вам нужно создать таблицу для хранения ключей сброса паролей. Для создания миграции для таблицы просто выполните команду auth:reminders-table интерфейса Artisan.

shphp artisan auth:reminders-table

php artisan migrate
+ 4.1

добавлено в 4.1 ()

Контроллер сброса паролей

Теперь мы готовы к созданию контроллера сброса паролей. Чтобы автоматически создать контроллер, вы можете использовать Artisan-команду shauth:reminders-controller, которая создаст файл RemindersController.php в вашем каталоге app/controllers.

shphp artisan auth:reminders-controller

В созданном контроллере уже будет метод PHPgetRemind(), который обрабатывает отображение вашей формы сброса пароля. Вам надо только создать шаблон password.remind. В этом шаблоне должна быть основная форма с полем email. Форма должна отправлять POST-запрос в действие RemindersController@postRemind.

Простая форма в шаблоне password.remind может выглядеть так:

PHP
<form action="{{ action('RemindersController@postRemind') }}" method="POST">
  <
input type="email" name="email">
  <
input type="submit" value="Send Reminder">
</
form>

В дополнение к PHPgetRemind() в созданном контроллере будет метод PHPpostRemind(), который обрабатывает отправку оповещений о сбросе пароля вашим пользователям по электронной почте. Этот метод предполагает наличие поля email в переменных POST. Если оповещение будет успешно отправлено пользователю по электронной почте, то в сессию будет передано сообщение status. Если оповещение не пройдёт, в сессию будет передано сообщение error.

В методе контроллера PHPpostRemind() вы можете изменить экземпляр сообщения перед его отправкой пользователю:

PHP
Password::remind(Input::only('email'), function($message)
{
  
$message->subject('Password Reminder');
});

Ваш пользователь получит по электронной почте ссылку, которая указывает на метод контроллера PHPgetReset(). Ключ сброса пароля, который используется для идентификации данной попытки сброса пароля, также будет передан методу контроллера. Действие уже настроено, чтобы вернуть шаблон password.reset, который вы должны создать. Ключ token будет передан в шаблон, и вы должны поместить этот ключ в скрытое поле формы token. Кроме поля token форма сброса пароля должна содержать поля email, password и password_confirmation. Форма должна отправлять POST-запрос в метод PHPRemindersController@postReset.

Простая форма в шаблоне password.reset может выглядеть так:

PHP
<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>

Наконец, метод PHPpostReset() отвечает за фактическое изменение пароля в хранилище. В этом действии контроллера замыкание, переданное в метод PHPPassword::reset(), устанавливает атрибут password для user и вызывает метод PHPsave. Конечно, это замыкание предполагает, что ваша модель user является моделью Eloquent. Однако вы можете изменить это замыкание по мере необходимости, чтобы оно было совместимым с системой хранения базы данных вашего приложения.

Если пароль успешно сброшен, пользователь будет перенаправлен в корень вашего приложения. Опять же, вы можете изменить URL этого перенаправления. Если сброс пароля не пройдёт, пользователь будет перенаправлен обратно в форму сброса, и в сессию будет передано сообщение error.

Проверка пароля

По умолчанию метод PHPPassword::reset() будет проверять, что пароли совпадают и содержат не менее шести символов. Вы можете настроить эти правила, используя метод PHPPassword::validator(), который принимает замыкание. В этом замыкании, вы можете делать любые проверки пароля. Обратите внимание, что вам не надо проверять совпадение паролей, фреймворк сделает это автоматически.

PHP
Password::validator(function($credentials)
{
  return 
strlen($credentials['password']) >= 6;
});

По умолчанию ключи сброса пароля истекают через один час. Вы можете изменить это с помощью параметра reminder.expire в вашем файле app/config/auth.php.

+ 4.0

добавлено в 4.0 ()

Раздел применим только к версии Laravel 4.0.

Отправка уведомления о сбросе пароля

Для отправки уведомления вы можете использовать метод PHPPassword::remind():

PHP
Route::post('password/remind', function ()
{
  
$credentials = array(
    
'email' => Input::get('email'),
    
'password' => Input::get('password'),
    
'password_confirmation' => Input::get('password_confirmation')
  );

  return 
Password::remind($credentials);
});

Заметьте, что параметры, переданные в метод PHPPassword::remind(), похожи на те, которые передаются методу PHPAuth::attempt(). Этот метод получит модель PHPUser и отправит соответствующее письмо со ссылкой для сброса. В шаблон письма будет передана переменная PHP$token, которая может быть использована для изменения пароля через форму его сброса. Кроме неё будет также передана переменная PHP$user.

Внимание: вы можете указать, какой шаблон должен использоваться при создании сообщения, изменив настройку приложения auth.reminder.email. Изначально фреймворк уже содержит нужный шаблон.

Вы можете изменить объект письма, которое отправляется пользователю, передав замыкание в виде второго аргумента методу PHPPassword::remind():

PHP
return Password::remind($credentials, function ($message$user) {
  
$message->subject('Ваше уведомление о сбросе.');
});

Как вы можете заметить, в маршруте мы напрямую возвращаем результат вызова метода PHPPassword::remind(). По умолчанию этот метод возвращает переадресацию на текущий адрес, если возникла ошибка при сбросе пароля, при этом устанавливается одноразовая переменная error, а также reason, которая используется для извлечения языковой строки из языкового файла reminders. Если пароль был успешно сброшен, то будет установлена одноразовая переменная success. Таким образом, шаблон для формы сброса пароля должен выглядеть примерно так:

PHP
@if (Session::has('error'))
  {{ 
trans(Session::get('reason')) }}
@elseif (
Session::has('success'))
  
На ваш e-mail было отправлено письмо с инструкциями о сбросе пароля.
@endif

<
input type="text" name="email">
<
input type="submit" value="Отправить письмо">

Сброс пароля (4.0)

Как только пользователь перешёл по ссылке в письме, он будет перенаправлен на форму со скрытым ключом token, а также полями password и password_confirmation. Ниже — пример маршрута для формы сброса:

PHP
Route::get('password/reset/{token}', function ($token) {
  return 
View::make('auth.reset')->with('token'$token);
});

А сама форма может выглядеть так:

PHP
@if (Session::has('error'))
  {{ 
trans(Session::get('reason')) }}
@endif

<
input type="hidden" name="token" value="{{ $token }}">
<
input type="text" name="email">
<
input type="password" name="password">
<
input type="password" name="password_confirmation">

Обратите внимание, что мы снова используем сессии для отображения ошибки, которая могла произойти при сбросе пароля. Дальше мы определяем POST-маршрут, который и произведёт сброс:

PHP
Route::post('password/reset/{token}', function () {
  
$credentials = array('email' => Input::get('email'));

  return 
Password::reset($credentials, function ($user$password) {
    
$user->password Hash::make($password);

    
$user->save();

    return 
Redirect::to('home');
  });
});

При успешном сбросе объект PHPUser и пароль будут переданы в замыкание, что позволит вам сохранить изменённую модель. После этого вы можете вернуть объект PHPRedirect или любой другой тип ответа, что и будет возвращено методом PHPPassword::reset(). Заметьте, что этот метод автоматически проверяет переданный ключ (token), данные для входа и совпадение введённых паролей.

По умолчанию время действия ключа для сброса пароля — час. Вы можете настроить это время с помощью параметра reminder.expire в вашем файле app/config/auth.php.

Также, по аналогии с методом PHPPassword::remind(), если во время сброса произошла ошибка метод PHPPassword::reset() вернёт объект PHPRedirect на текущий адрес с одноразовыми переменными error и reason.

Шифрование

Laravel предоставляет функции для устойчивого шифрования по алгоритму AES с помощью расширения mcrypt для PHP.

Шифрование строки

PHP
$encrypted Crypt::encrypt('секрет');

Внимание: версия 4.2 перешла на 128-битный AES, а 4.1 и ниже использовала 256-битный. Это значит, что преждезакодированные значения после обновления раскодировать не получится — см. руководство по обновлениюприм. пер.

Внимание: обязательно установите 16, 24 или 32-значный ключ key (до версии 4.2 — только 32-значный — прим. пер.) в файле app/config/app.php. Если этого не сделать, зашифрованные строки не будут безопасными.

Расшифровка строки

PHP
$decrypted Crypt::decrypt($encryptedValue);

Изменение алгоритма и режима шифрования

PHP
Crypt::setMode('ctr');

Crypt::setCipher($cipher);
+ 4.1

добавлено в 4.1 ()

Драйверы авторизации

Laravel предоставляет драйверы авторизации database и eloquent прямо из коробки. Для получения дополнительной информации о добавлении дополнительных драйверов авторизации прочитайте документации по расширению авторизации.

Комментарии (1)

evth

Насколько же просто реализовано восстановление пароля пользователем

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.