Рубрики
Uncategorized

Волшебные ссылки для входа в Laravel

Автор: Оззи Нехер ✏️ Если вы когда-либо пользовались таким сайтом, как Vercel или Medium, то, скорее всего, уже пользовались… Помеченный laravel, php.

Автор Оззи Неер ✏️

Если вы когда-либо пользовались таким сайтом, как Vercel или Medium, скорее всего, вы уже сталкивались с логином без пароля.

Обычно процесс выглядит следующим образом: введите свой адрес электронной почты -> форма отправки -> вам будет отправлено электронное письмо -> вы нажимаете на ссылку внутри -> вы вошли в систему.

Это довольно удобный поток для всех. Пользователям не нужно запоминать пароль с помощью произвольного набора правил веб-сайта, а веб-мастерам (люди все еще используют этот термин?) Не нужно беспокоиться об утечках паролей или о том, достаточно ли хорошо их шифрование.

В этой статье мы рассмотрим, как можно реализовать этот поток с помощью стандартной установки Laravel.

Мы будем исходить из того, что у вас есть рабочее представление о структуре Laravel MVC и что в вашей среде уже установлены как Composer, так и PHP.

Пожалуйста, обратите внимание, что блоки кода в этой статье могут не включать весь файл для краткости.

Настройка среды

Давайте начнем с создания нового приложения Laravel 8:

$ composer create-project laravel/laravel magic-links

Затем нам нужно cd в ваш проект и убедиться, что мы ввели наши учетные данные базы данных. Также не забудьте заранее создать базу данных.

В моем случае я использую PostgreSQL и я выполняю всю свою настройку через Таблицу плюс . Откройте файл .env :

# .env
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=magic_link
DB_USERNAME=postgres
DB_PASSWORD=postgres

Теперь наша база данных настроена, но пока не запускайте миграцию! Давайте взглянем на миграцию пользователей по умолчанию, которую Laravel создала для нас в база данных/migrations/2014_10_12_000000_create_users_table.php .

Вы увидите, что таблица пользователей по умолчанию содержит столбец для пароля. Поскольку мы выполняем аутентификацию без пароля, мы можем избавиться от этого:

public function up()
{
  Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->rememberToken();
    $table->timestamps();
  });
}

Продолжайте и сохраните файл после удаления этой строки. Пока мы наводим порядок, давайте продолжим и удалим миграцию для таблицы сброса пароля, так как она нам не понадобится:

$ rm database/migrations/2014_10_12_100000_create_password_resets_table.php

Наша начальная схема базы данных готова, поэтому давайте запустим наши миграции:

$ php artisan migrate

Давайте также удалим атрибут пароль из массива модели пользователя $fillable в app/Models/User.php поскольку он больше не существует:

protected $fillable = [
  'name',
  'email',
];

Мы также захотим настроить наш почтовый драйвер, чтобы мы могли просматривать ваши электронные письма для входа. Мне нравится использовать Mailtrap , который является бесплатным перехватчиком SMTP (вы можете отправлять электронные письма на любой адрес, и они будут отображаться только в Mailtrap, а не доставляться фактическому пользователю), но вы можете использовать любой, который вам нравится.

Если вы не хотите ничего настраивать, вы можете использовать почтовую программу log , и электронные письма будут отображаться в хранилище/журналы/laravel.log в виде необработанного текста.

Обратно в тот же файл .env , что и раньше:

# .env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=redacted
MAIL_PASSWORD=redacted
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@example.com

Теперь мы готовы приступить к строительству!

Наш подход

Мы говорили о том, как выглядит поток с точки зрения пользователя в начале этой статьи, но как это работает с технической точки зрения?

Что ж, учитывая пользователя, нам нужно иметь возможность отправлять ему уникальную ссылку, которая, когда он нажимает на нее, регистрирует его в своей учетной записи.

Это говорит нам о том, что нам, вероятно, потребуется сгенерировать какой-либо уникальный токен, связать его с пользователем, пытающимся войти в систему, построить маршрут, который просматривает этот токен и определяет, действителен ли он, а затем регистрирует пользователя. Мы также захотим разрешить использовать эти токены только один раз, и они будут действительны только в течение определенного периода времени после их создания.

Поскольку нам нужно отслеживать, использовался ли уже токен или нет, мы собираемся сохранить их в базе данных. Также будет удобно отслеживать, какой токен принадлежит какому пользователю, а также использовался ли токен или нет, и истек ли срок его действия.

Создайте тестового пользователя

В этой статье мы сосредоточимся только на процессе входа в систему. Вам предстоит создать страницу регистрации, хотя на ней будут выполнены все те же действия.

Из-за этого нам понадобится пользователь в базе данных для проверки входа в систему. Давайте создадим его с помощью tinker:

$ php artisan tinker
> User::create(['name' => 'Jane Doe', 'email' => 'test@example.com'])

Маршрут входа в систему

Мы начнем с создания контроллера AuthController , который мы будем использовать для управления функциями входа, проверки и выхода из системы:

$ php artisan make:controller AuthController

Теперь давайте зарегистрируем маршруты входа в систему в вашем приложении routes/web.php файл. Под маршрутом приветствия давайте определим группу маршрутов, которая защитит наши маршруты аутентификации с помощью промежуточного программного обеспечения guest , не позволяя людям, уже вошедшим в систему, просматривать их.

Внутри этой группы мы создадим два маршрута. Один для отображения страницы входа в систему, другой для обработки отправки формы. Мы также дадим им имена, чтобы мы могли легко ссылаться на них позже:

Route::group(['middleware' => ['guest']], function() {
  Route::get('login', [AuthController::class, 'showLogin'])->name('login.show');
  Route::post('login', [AuthController::class, 'login'])->name('login');
});

Теперь маршруты зарегистрированы, но нам нужно создать действия, которые будут реагировать на эти маршруты. Давайте создадим эти методы в созданном нами контроллере app/Http/Controllers/AuthController.php .

На данный момент наша страница входа в систему вернет представление, расположенное по адресу auth.войти (который мы создадим следующим), и создайте заполнитель логин метод, к которому мы вернемся, как только создадим нашу форму:

Мы собираемся использовать систему шаблонов Laravel Blade и CSS попутного ветра для наших представлений.

Поскольку основное внимание в этой статье уделяется внутренней логике, мы не будем вдаваться в подробности стиля. Я не хочу тратить время на настройку правильной конфигурации CSS, поэтому мы будем использовать это Попутный ветер CSS JIT CDN , который мы можем добавить в наш макет, который будет обрабатывать выбор правильных стилей.

Вы можете заметить вспышку стилей при первой загрузке страницы. Это связано с тем, что стили не существуют до тех пор, пока страница не загрузится. В производственной среде вы бы этого не хотели, но ради учебника это нормально.

Давайте начнем с создания общего макета, который мы можем использовать для всех наших страниц. Этот файл будет храниться в resources/views/layouts/app.blade.php :





  
  
  
  {{ $title }}


  @yield('content')
  


Есть несколько вещей, на которые я здесь укажу:

  • Заголовок страницы будет задан переменной $title , которую мы передадим в макет, когда будем выходить из него
  • Значение @yield("содержимое") Директива Blade – когда мы расширяемся от этого макета, мы будем использовать именованный раздел под названием “контент” для размещения содержимого нашей страницы.
  • Скрипт TailwindCSS JIT CDN, который мы используем для обработки наших стилей

Теперь, когда у нас есть макет, мы можем создать страницу регистрации в resources/views/auth/login.blade.php :

@extends('layouts.app', ['title' => 'Login'])
@section('content')
  

Login

@csrf
@error('email')

{{ $message }}

@enderror
@endsection

Здесь кое-что происходит, давайте кое-что проясним:

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем содержимое вашей страницы внутрь, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы отправили для входа в систему. Мы включаем скрытое поле CSRF с помощью директивы || @csrf || ( |Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем любые ошибки проверки, предоставленные Laravel, используя директиву || @error ||| подробнее здесь || ) || te || маршрут (“вход”) ||

Мы объявляем раздел под названием контент (помните @yield ранее?) и помещаем содержимое вашей страницы внутрь, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из routes/web.php файл – это запрос NPOST

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый scrlet’s, реализующий метод || входа || в нашем || AuthController ||. Поток будет выглядеть примерно так: проверить данные формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить свою электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

// app/Http/Controllers/AuthController.php
// near other use statements
use App\Models\User;

// inside class
public function login(Request $request)
{
  $data = $request->validate([
    'email' => ['required', 'email', 'exists:users,email'],
  ]);
  User::whereEmail($data['email'])->first()->sendLoginLink();
  session()->flash('success', true);
  return redirect()->back();
}

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || входа || в нашем || AuthController || Вот несколько вещей, которые мы здесь делаем: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице, в котором говорится, что им нужно проверить свою электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

  • Мы объявляем раздел под названием
  • контент (помните @yield
  • ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый scrlet’s, реализующий метод || login || в нашем || AuthController || На вышеуказанных шагах есть пара незавершенных задач, поэтому нам нужно их реализовать сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Мы объявляем раздел под названием контент (помните

@extends('layouts.app', ['title' => 'Login'])
@section('content')
  
@if(!session()->has('success'))

Login

@csrf
@error('email')

{{ $message }}

@enderror
@else

Please click the link sent to your email to finish logging in.

@endif
@endsection

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || login || в нашем || AuthController ||, где мы просто завернули форму в условное. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый scrlEt, реализующий метод || login || в нашем || AuthController ||, в котором говорится: Здесь мы просто завернули форму в условное. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

  • Мы объявляем раздел под названием
    • контент
    • (помните

Мы объявляем раздел под названием контент (помните @yield ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из

Мы объявляем раздел под названием контент (помните

public function sendLoginLink()
{
  // TODO
}

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || входа || в нашем || AuthController ||, чтобы снова отправить форму и убедиться, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || входа || в нашем || AuthController || Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || login || в нашем || AuthController || Для реализации функции sendLoginLink. Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || login || в нашем || AuthController || Для отражения подхода к токенам, который мы обсуждали выше, вот что нам нужно сделать сейчас: Реализация функции sendLoginLink Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

  1. Мы объявляем раздел под названием
  2. контент

Мы объявляем раздел под названием контент (помните @yield ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из

$ php artisan make:model -m LoginToken

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || login || в нашем || AuthController || Для необходимой нам миграции: Давайте создадим модель и миграцию ( || -m || ): Мы собираемся сохранить их в таблице под названием || login_tokens || . Отправьте пользователю электронное письмо со ссылкой на страницу, которая проверяет этот токен, Создайте уникальный токен и прикрепите его к пользователю Размышляя о подходе к токенам, который мы обсуждали выше, вот что нам нужно сделать сейчас: Реализация функции sendLoginLink Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

  • Мы объявляем раздел под названием
  • контент
  • (помните
  • @yield

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки Если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || login || в нашем || AuthController ||, чтобы завершить сгенерированную миграцию и добавить необходимые столбцы: Мы собираемся использовать для этого поле метки времени, так как отсутствие значения в этом столбце сообщит нам, использовалось ли оно, и, поскольку оно является меткой времени, оно также позволяет нам знать, когда оно было использовано – двойной выигрыш! Флаг, который сообщает нам, был ли уже использован токен или нет. Дата, указывающая, когда истекает срок действия токена, Ассоциация, которая связывает его с запрашивающим пользователем. Мы создаем уникальный токен для URL-адреса Для нужной нам миграции: Давайте создадим модель и миграцию ( || -m || ): Мы собираемся сохранить их в таблице под названием || login_tokens || . Отправьте пользователю электронное письмо со ссылкой на страницу, которая проверяет этот токен, Создайте уникальный токен и прикрепите его к пользователю Размышляя о подходе к токенам, который мы обсуждали выше, вот что нам нужно сделать сейчас: Реализация функции sendLoginLink Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

Schema::create('login_tokens', function (Blueprint $table) {
  $table->id();
  $table->unsignedBigInteger('user_id');
  $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
  $table->string('token')->unique();
  $table->timestamp('consumed_at')->nullable();
  $table->timestamp('expires_at');
  $table->timestamps();
});

Мы объявляем раздел под названием || контент || (помните || @yield || ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из || routes/web.php || файл – это запрос NPOST || в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву || @csrf || ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод || входа || в нашем || AuthController ||, чтобы убедиться, что после этого выполните миграцию: откройте сгенерированную миграцию и добавьте необходимые столбцы: Мы собираемся использовать для этого поле метки времени, так как отсутствие значения в этом столбце сообщит нам, использовалось ли оно, и, поскольку оно является меткой времени, оно также позволяет нам знать, когда оно было использовано – двойной выигрыш! Флаг, который сообщает нам, был ли уже использован токен или нет. Дата, указывающая, когда истекает срок действия токена, Ассоциация, которая связывает его с запрашивающим пользователем. Мы создаем уникальный токен для URL-адреса Для нужной нам миграции: Давайте создадим модель и миграцию ( || -m || ): Мы собираемся сохранить их в таблице под названием || login_tokens || . Отправьте пользователю электронное письмо со ссылкой на страницу, которая проверяет этот токен, Создайте уникальный токен и прикрепите его к пользователю Размышляя о подходе к токенам, который мы обсуждали выше, вот что нам нужно сделать сейчас: Реализация функции sendLoginLink Конечно, вы еще не получили электронное письмо, но теперь мы можем перейти к этому шагу. Теперь отправьте форму еще раз и убедитесь, что вы видите сообщение об успешном завершении, как показано ниже: Откройте || app/Models/User.php || и создайте пустой метод, чтобы заполнить его место: мне нравится хранить подобную логику в самой модели, чтобы мы могли повторно использовать ее в нашем приложении позже. Функция sendLoginLink || для модели || пользователя ||. Теперь, если вы снова отправите эту форму, вы увидите сообщение об ошибке, в котором говорится, что нам нужно это реализовать || Да – сообщите пользователю, что его учетная запись была создана, и проверьте их электронную почту на наличие ссылки Нет – вместо этого покажите регистрационную форму Мы только что успешно отправили форму? Это говорит о том, что здесь мы просто завернули форму в условное выражение. Вернуться в || resources/views/auth/login.blade.php Мы начнем с обновления нашего представления входа в систему, чтобы проверить это логическое значение успеха, скрыть нашу форму и показать пользователю сообщение, если оно присутствует. На вышеуказанных этапах есть несколько незавершенных задач, поэтому нам нужно будет выполнить их сейчас. Мы вводим значение в сеанс, указывающее, что запрос выполнен успешно, а затем возвращаем пользователя обратно на страницу входа, которую нам нужно будет реализовать sendLoginLink || Мы находим пользователя по предоставленной электронной почте и вызываем функцию проверки данных формы – сообщаем, что электронная почта требуется, должна быть действительной электронной почтой и существовать в нашей базе данных. Здесь мы делаем несколько вещей: Поток будет выглядеть примерно так: проверка данных формы -> отправить ссылку для входа -> показать сообщение пользователю на странице с просьбой проверить их электронную почту. отправьте им ссылку, чтобы завершить вход в систему. een, потому что наш метод || логин ||, который мы определили ранее, пуст. rs, предоставленный Laravel с использованием директивы || @error ||| подробнее читайте здесь || ) |/te || маршрут(“вход”) ||

$ php artisan migrate

Мы объявляем раздел под названием контент (помните

  • Мы объявляем раздел под названием контент (помните
  • @yield ранее?) и помещаем внутрь содержимое нашей страницы, которое будет отображено в макете. Некоторые базовые контейнеры и стили применяются для центрирования формы в середине экрана Действие формы указывает на именованный маршрут, который, если мы помним из routes/web.php файл - это запрос NPOST в нашем контроллере, который мы дали для входа в систему. Мы включаем скрытое поле CSRF, используя директиву @csrf ( | Если вы загружаете страницу, она должна выглядеть так: Мы условно показываем основные данные, мы просто запрашиваем адрес электронной почты пользователя. любая ошибка проверки, если мы отправим форму прямо сейчас, вы просто увидите пустой белый SCRLET, реализующий метод login в нашем
  • AuthController , чтобы установить наше свойство $guarded
class LoginToken extends Model
{
  use HasFactory;

  protected $guarded = [];
  protected $dates = [
    'expires_at', 'consumed_at',
  ];

  public function user()
  {
    return $this->belongsTo(User::class);
  }
}

Также неплохо разместить обратную ассоциацию в пользовательской модели:

// inside app/Models/User.php
public function loginTokens()
{
  return $this->hasMany(LoginToken::class);
}

Теперь, когда у нас настроена модель, мы можем выполнить первый шаг нашей функции отправить ссылку для входа() , которая создает токен.

Вернуться внутрь app/Models/User.php мы собираемся создать токен для пользователя, используя новую ассоциацию loginTokens() , которую мы только что создали, и дать ему случайную строку, используя помощник Str из Laravel, срок действия которой истекает через 15 месяцев.

Потому что мы установили expire_at и consumed_at в качестве дат в модели токена входа мы можем просто передать данные fluent, и они будут соответствующим образом преобразованы. Мы также будем хэшировать токен перед тем, как вставить его в базу данных, чтобы в случае взлома этой таблицы никто не мог увидеть необработанные значения токена.

Мы используем воспроизводимый хэш, чтобы при необходимости мы могли просмотреть его позже:

use Illuminate\Support\Str;

public function sendLoginLink()
{
    $plaintext = Str::random(32);
    $token = $this->loginTokens()->create([
      'token' => hash('sha256', $plaintext),
      'expires_at' => now()->addMinutes(15),
    ]);
    // todo send email
}

Теперь, когда у нас есть токен, мы можем отправить пользователю электронное письмо, содержащее ссылку с (открытым текстом) токеном в URL-адресе, который подтвердит их сеанс. Маркер должен быть в URL-адресе, чтобы мы могли посмотреть, для какого пользователя он предназначен.

Мы не просто хотим использовать идентификатор Вход в систему потому что тогда пользователь потенциально может перейти один за другим, чтобы найти правильный URL-адрес. Позже мы рассмотрим другой способ защиты от этого.

Начните с создания класса почтовой программы, который будет представлять электронную почту:

$ php artisan make:mail MagicLoginLink

Откройте почтовую программу, созданную по адресу app/Mail/MagicLoginLink.php и введите следующее:

plaintextToken = $plaintextToken;
    $this->expiresAt = $expiresAt;
  }

  public function build()
  {
    return $this->subject(
      config('app.name') . ' Login Verification'
    )->markdown('emails.magic-login-link', [
      'url' => URL::temporarySignedRoute('verify-login', $this->expiresAt, [
        'token' => $this->plaintextToken,
      ]),
    ]);
  }
}

Вот что происходит – почтовая программа примет маркер открытого текста и срок годности и храните его в общедоступных свойствах. Это позволит нам использовать его позже в методе build() при его составлении.

Внутри метода build() мы задаем тему электронного письма и указываем ему искать представление в формате markdown внутри resources/views/emails/magic-login-link.blade.php . Laravel предоставляет некоторые стили по умолчанию для электронных писем с уценкой, которыми мы воспользуемся через мгновение.

Мы также передаем переменную url в представление, которое будет ссылкой, по которой пользователь нажимает.

Это свойство url является временным подписанным URL . Он принимает именованный маршрут, дату истечения срока действия (которую мы хотим использовать для истечения срока действия наших токенов) и любые параметры (в данном случае токен – это сгенерированная нами случайная строка без хэша). Подписанный URL-адрес гарантирует, что URL-адрес вообще не был изменен путем хэширования URL-адреса с секретом, известным только Laravel.

Несмотря на то, что мы собираемся добавить проверки в наш маршрут verify-login , чтобы убедиться, что наш токен все еще действителен (на основе свойств expire_at и consumed_at ), подписание URL-адреса обеспечивает нам дополнительную безопасность на уровне платформы, поскольку никто не сможет перебрать маршрут verify-login со случайными токенами, чтобы узнать, смогут ли они найти тот, который их регистрирует.

Теперь нам нужно реализовать это представление уценки по адресу resources/views/emails/magic-login-link.blade.php . Возможно, вам интересно, почему расширение .blade.php . Это связано с тем, что, хотя мы пишем markdown в этом файле, мы можем использовать директивы Blade внутри для создания повторно используемых компонентов, которые мы можем использовать в наших электронных письмах.

Laravel предоставляет нам готовые компоненты из коробки, чтобы сразу приступить к работе. Мы используем mail::сообщение , которое дает нам макет и призыв к действию с помощью кнопки mail:: :

@component('mail::message')
  Hello, to finish logging in please click the link below
  @component('mail::button', ['url' => $url])
    Click to login
  @endcomponent
@endcomponent

Теперь, когда у нас есть содержимое электронной почты, мы можем завершить метод отправить ссылку для входа() , фактически отправив электронное письмо. Мы собираемся использовать Почта предоставляется Laravel для указания электронной почты пользователей, на которую мы ее отправляем, и что содержимое электронной почты должно быть создано из класса MagicLoginLink , который мы только что закончили настраивать.

Мы также используем очередь() вместо отправить() чтобы электронное письмо отправлялось в фоновом режиме, а не во время текущего запроса. Убедитесь, что у вас правильно настроен драйвер очереди или что вы используете драйвер sync (это значение по умолчанию), если вы хотите, чтобы это произошло немедленно.

Вернуться в app/Models/User.php :

use Illuminate\Support\Facades\Mail;
use App\Mail\MagicLoginLink;

public function sendLoginLink()
{
  $plaintext = Str::random(32);
  $token = $this->loginTokens()->create([
    'token' => hash('sha256', $plaintext),
    'expires_at' => now()->addMinutes(15),
  ]);
  Mail::to($this->email)->queue(new MagicLoginLink($plaintext, $token->expires_at));
}

Если бы вы отправили нашу форму для входа, то теперь увидели бы электронное письмо, которое выглядит следующим образом:

Маршрут проверки

Если вы попытались перейти по ссылке, вы, вероятно, получили сообщение об ошибке 404. Это потому, что в нашем электронном письме мы отправили пользователю ссылку на маршрут проверка входа с именем, но мы его еще не создали!

Зарегистрируйте маршрут в группе маршрутов внутри routes/web.php :

Route::group(['middleware' => ['guest']], function() {
  Route::get('login', [AuthController::class, 'showLogin'])->name('login.show');
  Route::post('login', [AuthController::class, 'login'])->name('login');
  Route::get('verify-login/{token}', [AuthController::class, 'verifyLogin'])->name('verify-login');
});

И затем мы создадим реализацию внутри нашего класса AuthController с помощью метода verifyLogin :

public function verifyLogin(Request $request, $token)
{
  $token = \App\Models\LoginToken::whereToken(hash('sha256', $token))->firstOrFail();
  abort_unless($request->hasValidSignature() && $token->isValid(), 401);
  $token->consume();
  Auth::login($token->user);
  return redirect('/');
}

Здесь мы делаем следующее:

  • Поиск токена путем хеширования значения открытого текста и сравнения его с хэшированной версией в нашей базе данных (выдает 404, если не найден – через firstOrFail() )
  • Прерывание запроса с кодом состояния 401, если токен недействителен или подписанный URL-адрес недействителен (вы можете пофантазировать здесь, если хотите показать представление или что-то, позволяющее пользователю узнать больше информации, но ради этого урока мы просто убьем запрос)
  • Маркировка маркера как используемого, чтобы его нельзя было использовать снова
  • Вход пользователя, связанного с токеном
  • Перенаправление их на домашнюю страницу

Мы вызываем пару методов для токена, которые на самом деле еще не существуют, поэтому давайте создадим их:

  • является действительным() будет истинным, если токен еще не был использован ( consumed_at ) и если срок его действия не истек ( expire_at )
  • Мы извлекем просроченные и использованные, проверив их собственные функции, чтобы сделать их более удобочитаемыми
  • consume() собирается установить свойство consumed_at на текущую метку времени

Мне нравится инкапсулировать эту логику непосредственно в модель, чтобы ее было легко читать и повторно использовать. Откройся app/Models/LoginToken.php :

public function isValid()
{
  return !$this->isExpired() && !$this->isConsumed();
}

public function isExpired()
{
  return $this->expires_at->isBefore(now());
}

public function isConsumed()
{
  return $this->consumed_at !== null;
}

public function consume()
{
  $this->consumed_at = now();
  $this->save();
}

Если бы вы сейчас нажали на эту ссылку для входа со своего электронного письма, вы были бы перенаправлены на маршрут / !

Вы также заметите, что если вы снова нажмете на ссылку, вам будет показан экран ошибки, потому что теперь он недействителен.

Последние штрихи

Теперь, когда наш поток аутентификации работает, давайте защитим наш корневой маршрут, чтобы его могли видеть только те, кто вошел в систему, и добавим способ выхода из системы, чтобы мы могли повторить этот процесс.

Для начала отредактируйте корневой маршрут по умолчанию в app/web.php для добавления аутентификации промежуточного программного обеспечения:

Route::get('/', function () {
    return view('welcome');
})->middleware('auth');

Давайте также настроим это представление приветствия по умолчанию, чтобы показать немного информации о нашем вошедшем в систему пользователе, а также предоставить ссылку для выхода из системы. Заменить содержимое resources/views/welcome.blade.php со следующим:

@extends('layouts.app', ['title' => 'Home'])
@section('content')
  

Logged in as {{ Auth::user()->name }}

Logout
@endsection

И, наконец, маршрут выхода из системы, который забудет наш сеанс и вернет нас на экран входа в систему. Откройся routes/web.php еще раз и добавьте этот маршрут в нижнюю часть файла:

Route::get('logout', [AuthController::class, 'logout'])->name('logout');

И, наконец, нам нужно реализовать действие выхода из системы в нашем AuthController :

public function logout()
{
  Auth::logout();
  return redirect(route('login'));
}

Теперь ваша домашняя страница должна выглядеть так, и ее могут просматривать только те, кто вошел в систему:

Вывод

Это обертка! Мы проделали большую работу, но вы заметите, что общий код, который мы написали, довольно низок для такой функции. Надеюсь, по пути ты научился одному-двум трюкам.

Полный исходный код можно посмотреть здесь .

Войдите в систему: полная видимость ваших веб-приложений

Log Rocket – это решение для мониторинга интерфейсных приложений, которое позволяет воспроизводить проблемы так, как если бы они происходили в вашем собственном браузере. Вместо того, чтобы гадать, почему возникают ошибки, или запрашивать у пользователей скриншоты и дампы журналов, Log Rocket позволяет воспроизвести сеанс, чтобы быстро понять, что пошло не так. Он отлично работает с любым приложением, независимо от платформы, и имеет плагины для регистрации дополнительного контекста из Redux, Vuex и ngrx/store.

В дополнение к регистрации действий и состояний Redux, Log Rocket записывает журналы консоли, ошибки JavaScript, трассировки стека, сетевые запросы/ответы с заголовками + тела, метаданные браузера и пользовательские журналы. Он также использует DOM для записи HTML и CSS на странице, воссоздавая идеальные по пикселям видео даже самых сложных одностраничных приложений.

Попробуйте это бесплатно .

Оригинал: “https://dev.to/logrocket/magic-login-links-with-laravel-13d4”