Начиная с версии 5.6.12 Laravel обзавелся полезным функционалом «подписи» маршрутов. Так как я тяготею к криптографии я решила углубленно разобраться с этой фичей и рассказать как ею пользоваться.
Посмотрим что гласит официальная документация:
"Подписанные URL обладают хэшом «подписи», добавленным к строке запроса, что позволяет Laravel проверять, не был ли URL изменен с момента его создания. Подписанные URL-адреса особенно полезны для маршрутов, которые являются общедоступными, но требуют уровня защиты от манипулирования URL-адресами."
Итак, статья будет состоять из таких частей:
"Подписанные URL обладают хэшом «подписи», добавленным к строке запроса, что позволяет Laravel проверять, не был ли URL изменен с момента его создания. Подписанные URL-адреса особенно полезны для маршрутов, которые являются общедоступными, но требуют уровня защиты от манипулирования URL-адресами."
Итак, статья будет состоять из таких частей:
- Зачем?
- Как пользоваться?
- Как работает?
Примеры использования:
- Вам необходимо отправить письмо пользователю с простым вопросом и ответом да/нет. Например, пойдет ли он на мероприятие. Если пользователь не авторизован на сайте - ему придется входить в систему, и скорее всего – он этого не сделает и вы останетесь без ответа;
- Вам необходимо подтвердить почтовый ящик пользователя. Задача та же – необходимо чтобы без авторизации он смог подтвердить данные.
Здесь нам придут на помощь подписанные маршруты. Пользователю не придется входить в систему чтобы перейти по ссылке, но ссылка может достоверно идентифицировать переданную информацию, а именно то, что она не была изменена.
Кстати, в Laravel 5.7 на базе подписанных маршрутов появился встроенный функционал подтверждения ящика электронной почты пользователя.
Разберем на практике второй случай. Нам необходимо, к примеру, подтвердить смену почтового ящика пользователя отправкой ему письма на новый ящик с подтверждающей ссылкой.
Убедитесь, что в Http/Kernel.php у вас есть посредник signed:
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];
Создаем такой маршрут.
use Illuminate\Http\Request;
Route::get('email/{email}/{user}', function ($email, $user) {
if (! $request->hasValidSignature()) {
abort(401);
}
// Action
})->name('changeEmail')->middleware('signed');
В данном случае нам необходима будет информация о новом email и id пользователя для внесения данных об измененном ящике в базу. Маршрут и параметры могут быть любыми. Главное добавить на него посредника signed и имя.
Чтобы обратиться к нашему маршруту сгенерируем ссылку с данными:
use \Illuminate\Support\Facades\URL;
$url = URL::temporarySignedRoute('changeEmail', now()->addHour(), [
'email' => 'test@test.com',
'user' => 1
]);
Эту ссылку мы и поместим в письмо с запросом на подтверждение ящика. В данном случае мы создали временно действующую ссылку (1 час) использовав temporarySignedRoute.
Laravel сгенерирует ссылку вида:
Теперь, используя данную ссылку, если какие-то данные в ней изменятся (id пользователя, или какой-то символ из подписи, почтового ящика) Laravel выбросит исключение Illuminate\Routing\Exceptions\InvalidSignatureException. Это защищает приложение от грубого перебора и нарушения целостности данных.
Если нет необходимости ограничивать время действия ссылки, то просто используйте signedRoute.
$url = URL::signedRoute
('changeEmail', [
'email' => 'test@test.com',
'user' => 1
]);
А теперь раздел для самых любопытных или интересующихся криптосоставляющей вопроса.
Собственно, самой наглядной функцией всей этой системы является \Illuminate\Routing\UrlGenerator::signedRoute.
Из чего состоит подпись?
Это HMAC хэш (sha256) от самого маршрута (в нашем случае это «http://test.local/email/test@test.com/1» + параметр окончания срока действия ссылки «?expires=1563484975» в формате UNIX timestamp).
Ключом шифрования является секретный ключ приложения, который мы генерируем при создании приложения командой key:generate и который стоит в .env.
Проверка подписи происходит повторным взятием от ссылки (http://test.local/email/test@test.com/1?expires=1563484975) HMAC хэша и его сверкой с подписью.
Вот и вся магия!
Надеюсь, я смогла доходчиво рассказать о том, как пользоваться подписанными маршрутами и как это работает :)
Источники:
Источники:
- Getting Started with Signed Routes in Laravel https://laravel-news.com/signed-routes
- URL Generation https://laravel.com/docs/5.8/urls#signed-urls
- HMAC https://ru.wikipedia.org/wiki/HMAC
Комментарии
Отправить комментарий