Недавно я работал над проектом, где одной из болевых точек был пароль пользователя. Администратор добавлял пользователей в приложение, поэтому они не имеют пароля, а заставлять их придумывать пароль при первом после регистрации входе было крайне неудобно.
Итак, мы решили попробовать метод беспарольного входа. Если Вы никогда не имели возможности работать с этим, мы расскажем как это работает:
На странице входа в систему пользователь вводит свой email-адрес, на который получит ссылку на вход. Переход по ссылке подтверждает личность пользователя без необходимости ввода пароля, так как ссылка для каждого входа пользователя уникальная.
Начнем творить!

Вначале мы создадим наше приложение, подключив аутентификацию:
Теперь у нас есть все необходимые для авторизации файлы, в том числе вьюхи. Давайте начнем с них.
Конечно, сочетание логина с паролем довольно хорошая идея, но нам нужно отказаться от поля ввода пароля на обеих формах.
Откройте файл `resources/views/auth/login.blade.php` и удалите группу, отвечающую за ввод пароля (label, input и обертка ). Сохраняем, закрываем.
Теперь открываем файл `resources/views/auth/register.blade.php` и удаляем группы, отвечающие за ввод пароля (`password`) и подтверждения пароля (`password-reset`). Сохраняем, закрываем.
Позже Вы можете добавить инструкцию о методе входа на странице аутентификации, а также разместите ссылки на сброс пароля, но это позже.
Итак, нам нужно изменить роут, указывающий на точки входа и регистрации. Взглянем на контроллер ` AuthController`.
Во-первых, мы заметим метод `validator`, возвращающий валидацию поля пароля. Так как он отвечает за процесс регистрации учетной записи, нам нужно избавиться от его привязки к паролю.
В конечном итоге, функция должна выглядеть так:
То же самое мы сделаем для метода `Create`, приведя его к виду:
Как Вы можете видеть, здесь нет методов для регистрации пользователей. Они скрыты в трейте `AuthenticatesAndRegistersUsers`, который использует трейты аутентификации `AuthenticatesUsers` и регистрации `RegistersUsers`. Вы можете перейти к трейту `AuthenticatesUsers` и в конце файла найти метод аутентификации пользователей под именем `login`.
Все, что там происходит, основывается на защищенных паролях, хотя этот метод можно и заменить…
Целью нашего нового метода является отправка на email пользователя ссылки для входа в систему. Давайте вернемся к контроллеру `AuthController` и добавим метод входа в систему, перекрывающий `login` в `AuthenticatesUsers`:
Подтвердить реальность email адреса для зарегистрированного пользователя очень просто:
Далее, нам необходимо отправить пользователю ссылку на вход. Это займет немного больше времени.
Если Вы знакомы с формой структуры базы данных `password_reset`, то Вам будет проще, т.к. мы будем создавать нечто похожее. Каждый раз, когда кто-то пытается войти в систему, нам нужно добавлять запись в таблицу, которая будет фиксировать адрес электронной почты и уникальный токен, отправляемые в электронном письме в качестве URL, а также дату создания и срок жизни записи.
В конечном итоге мы будем использовать URL-адрес для создания (и проверки), например: `myapp.com/auth/email-authenticate/09ajfpoib23li4ub123p984h1234`. Так как срок жизни токена ограничен, мы должны связать этот URL с конкретным пользователем, отслеживая email, токен и дату создания для каждой записи таблицы.
Итак, создадим для него миграцию:
И добавим в нее несколько полей:
Теперь, давайте создадим модель.
Отредактировать файл (`app/EmailLogin.php`) и сделать его простым для нас, создав экземпляр с нужными свойствами:
И когда хотим найти пользователя, мы должны использовать электронную почту, а не идентификатор, вручную связав столбец email:
Теперь мы готовы к созданию email-сообщения. Мы будем использовать URL-адрес, содержащий уникальный токен, сгенерированный заранее.
Нужно понять, как мы будем создавать и хранить токен. Для этого, нам нужно создать экземпляр `EmailLogin`, так что приступим:
Давайте добавим этот метод в `EmailLogin`:
Мы генерируем рандомный токен и создаем экземпляр класса `EmailToken`, получая его обратно.
Итак, нам нужно использовать `EmailToken` для формирования URL перед отправкой сообщения пользователю.
Давайте создадим для него роут:
… и добавим метод в контроллер для работы этого маршрута:
… и еще добавим метод `validFromToken` для проверки токена:
Теперь у нас есть входящий роут, учитывающий актуальность каждого токена. Если токен актуален — пользователь будет перенаправлен по адресу `mysite.ru/home`.
Что ж, давайте отправим письмо.
Добавим вызов `call email` в наш контроллер:
… и создадим шаблон:
Вы можете оформить шаблон любым удобным способом, но мы просто используем текст: «Эй, мы отправили мыло, чтобы его проверить. Это все.»
Взглянем на нашу систему. У нас есть новый метод `login` в контроллере `AuthController`:
Мы создали несколько вьюх, обновив существующие (убрали в них записи о пароле). Также создали новый роут в `/auth/email-authenticate`. И также создали миграцию `EmailLogin` с классом всех его потребностей.
И… профит! Поместите все примеры в Ваш код и получите полностью функциональную систему беспарольного входа.
Для регистрации пользователя нужно будет узнать всего-лишь их email-адрес. И при авторизации кроме их email-адреса больше ничего не нужно будет запоминать и вводить. Больше нет забытых паролей. Бум!
При переводе статьи была произведена адаптация информации для лучшей читаемости русскоговорящих пользователей.
Итак, мы решили попробовать метод беспарольного входа. Если Вы никогда не имели возможности работать с этим, мы расскажем как это работает:
На странице входа в систему пользователь вводит свой email-адрес, на который получит ссылку на вход. Переход по ссылке подтверждает личность пользователя без необходимости ввода пароля, так как ссылка для каждого входа пользователя уникальная.
Начнем творить!

Новое приложение и make:auth
Вначале мы создадим наше приложение, подключив аутентификацию:
laravel new medium-login
cd medium-login
php artisan make:auth
Теперь у нас есть все необходимые для авторизации файлы, в том числе вьюхи. Давайте начнем с них.
Изменение страницы входа и регистрации
Конечно, сочетание логина с паролем довольно хорошая идея, но нам нужно отказаться от поля ввода пароля на обеих формах.
Откройте файл `resources/views/auth/login.blade.php` и удалите группу, отвечающую за ввод пароля (label, input и обертка ). Сохраняем, закрываем.
Теперь открываем файл `resources/views/auth/register.blade.php` и удаляем группы, отвечающие за ввод пароля (`password`) и подтверждения пароля (`password-reset`). Сохраняем, закрываем.
Позже Вы можете добавить инструкцию о методе входа на странице аутентификации, а также разместите ссылки на сброс пароля, но это позже.
Изменение регистрационных роутов
Итак, нам нужно изменить роут, указывающий на точки входа и регистрации. Взглянем на контроллер ` AuthController`.
Во-первых, мы заметим метод `validator`, возвращающий валидацию поля пароля. Так как он отвечает за процесс регистрации учетной записи, нам нужно избавиться от его привязки к паролю.
В конечном итоге, функция должна выглядеть так:
// app/http/Controllers/Auth/AuthController.php
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
]);
}
То же самое мы сделаем для метода `Create`, приведя его к виду:
// app/http/Controllers/Auth/AuthController.php
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
]);
}
Перекрытие роута `login`
Как Вы можете видеть, здесь нет методов для регистрации пользователей. Они скрыты в трейте `AuthenticatesAndRegistersUsers`, который использует трейты аутентификации `AuthenticatesUsers` и регистрации `RegistersUsers`. Вы можете перейти к трейту `AuthenticatesUsers` и в конце файла найти метод аутентификации пользователей под именем `login`.
Все, что там происходит, основывается на защищенных паролях, хотя этот метод можно и заменить…
Целью нашего нового метода является отправка на email пользователя ссылки для входа в систему. Давайте вернемся к контроллеру `AuthController` и добавим метод входа в систему, перекрывающий `login` в `AuthenticatesUsers`:
// app/http/Controllers/Auth/AuthController.php
public function login(Request $request)
{
// validate that this is a real email address
// send off a login email
// show the users a view saying "check your email"
}
Подтверждение реальности email-адреса
Подтвердить реальность email адреса для зарегистрированного пользователя очень просто:
$this->validate($request, ['email' => 'required|email|exists:users']);
Отправка email-сообщения
Далее, нам необходимо отправить пользователю ссылку на вход. Это займет немного больше времени.
Создание структуры для формирования и проверки токенов email
Если Вы знакомы с формой структуры базы данных `password_reset`, то Вам будет проще, т.к. мы будем создавать нечто похожее. Каждый раз, когда кто-то пытается войти в систему, нам нужно добавлять запись в таблицу, которая будет фиксировать адрес электронной почты и уникальный токен, отправляемые в электронном письме в качестве URL, а также дату создания и срок жизни записи.
В конечном итоге мы будем использовать URL-адрес для создания (и проверки), например: `myapp.com/auth/email-authenticate/09ajfpoib23li4ub123p984h1234`. Так как срок жизни токена ограничен, мы должны связать этот URL с конкретным пользователем, отслеживая email, токен и дату создания для каждой записи таблицы.
Итак, создадим для него миграцию:
php artisan make:migration create_email_logins_table --create=email_logins
И добавим в нее несколько полей:
Schema::create('email_logins', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token')->index();
$table->timestamps();
});
Примечание: при желании можно использовать значение колонки `id` вместо токена, но есть несколько причин более лучших вариантов. Во всяком случае, решать Вам.
Теперь, давайте создадим модель.
php artisan make:model EmailLogin
Отредактировать файл (`app/EmailLogin.php`) и сделать его простым для нас, создав экземпляр с нужными свойствами:
class EmailLogin extends Model
{
public $fillable = ['email', 'token'];
}
И когда хотим найти пользователя, мы должны использовать электронную почту, а не идентификатор, вручную связав столбец email:
class EmailLogin extends Model
{
public $fillable = ['email', 'token'];
public function user()
{
return $this->hasOne(\App\User::class, 'email', 'email');
}
}
Создание токена
Теперь мы готовы к созданию email-сообщения. Мы будем использовать URL-адрес, содержащий уникальный токен, сгенерированный заранее.
Нужно понять, как мы будем создавать и хранить токен. Для этого, нам нужно создать экземпляр `EmailLogin`, так что приступим:
public function login()
{
$this->validate($request, ['email' => 'required|email|exists:users']);
$emailLogin = EmailLogin::createForEmail($request->input('email'));
}
Давайте добавим этот метод в `EmailLogin`:
class EmailLogin extends Model
{
...
public static function createForEmail($email)
{
return self::create([
'email' => $email,
'token' => str_random(20)
]);
}
}
Мы генерируем рандомный токен и создаем экземпляр класса `EmailToken`, получая его обратно.
Формирование URL для отправки по email
Итак, нам нужно использовать `EmailToken` для формирования URL перед отправкой сообщения пользователю.
public function login()
{
$this->validate($request, ['email' => 'required|email|exists:users']);
$emailLogin = EmailLogin::createForEmail($request->input('email'));
$url = route('auth.email-authenticate', [
'token' => $emailLogin->token
]);
}
Давайте создадим для него роут:
// app/Http/routes.php
Route::get('auth/email-authenticate/{token}', [
'as' => 'auth.email-authenticate',
'uses' => 'Auth\AuthController@authenticateEmail'
]);
… и добавим метод в контроллер для работы этого маршрута:
class AuthController
{
...
public function authenticateEmail($token)
{
$emailLogin = EmailLogin::validFromToken($token);
Auth::login($emailLogin->user);
return redirect('home');
}
}
… и еще добавим метод `validFromToken` для проверки токена:
class EmailLogin
{
...
public static function validFromToken($token)
{
return self::where('token', $token)
->where('created_at', '>', Carbon::parse('-15 minutes'))
->firstOrFail();
}
Теперь у нас есть входящий роут, учитывающий актуальность каждого токена. Если токен актуален — пользователь будет перенаправлен по адресу `mysite.ru/home`.
Что ж, давайте отправим письмо.
Отправка письма
Добавим вызов `call email` в наш контроллер:
public function login()
{
...
Mail::send('auth.emails.email-login', ['url' => $url], function ($m) use ($request) {
$m->from('noreply@myapp.com', 'MyApp');
$m->to($request->input('email'))->subject('MyApp Login');
});
… и создадим шаблон:
<!-- resources/views/auth/emails/email-login.blade.php -->
Log in to MyApp here: <a href="{{ $url }}">{{ $url }}</a>
Возвращение шаблона
Вы можете оформить шаблон любым удобным способом, но мы просто используем текст: «Эй, мы отправили мыло, чтобы его проверить. Это все.»
return 'Login email sent. Go check your email.';
Совместный вход
Взглянем на нашу систему. У нас есть новый метод `login` в контроллере `AuthController`:
public function login(Request $request)
{
$this->validate($request, ['email' => 'required|exists:users']);
$emailLogin = EmailLogin::createForEmail($request->input('email'));
$url = route('auth.email-authenticate', [
'token' => $emailLogin->token
]);
Mail::send('auth.emails.email-login', ['url' => $url], function ($m) use ($request) {
$m->from('noreply@myapp.com', 'MyApp');
$m->to($request->input('email'))->subject('MyApp login');
});
return 'Login email sent. Go check your email.';
}
Мы создали несколько вьюх, обновив существующие (убрали в них записи о пароле). Также создали новый роут в `/auth/email-authenticate`. И также создали миграцию `EmailLogin` с классом всех его потребностей.
Это все!
И… профит! Поместите все примеры в Ваш код и получите полностью функциональную систему беспарольного входа.
Для регистрации пользователя нужно будет узнать всего-лишь их email-адрес. И при авторизации кроме их email-адреса больше ничего не нужно будет запоминать и вводить. Больше нет забытых паролей. Бум!
От переводчика
При переводе статьи была произведена адаптация информации для лучшей читаемости русскоговорящих пользователей.