E-mail подтверждение регистрации пользователя в Laravel

Добавлено: 17/09/2016 06:47 |  Обновлено: 03/03/2019 14:22 |  Добавил: nick |  Просмотры: 16387 Комментарии: 22
Вводная часть
Сейчас уже довольно распространена процедура подтверждения введенного пользователем почтового ящика при регистрации, как это делается в Laravel описано в этом материале. Пример работает в Laravel 5.3-5.7.
В разделах ниже вы узнаете как добавить функционал подтверждения регистрации пользователя в свой проект. В первом разделе все создается вручную (функционал аутентификации + процедура подтверждения регистрации). Во втором разделе используется аутентификация из коробки (до версии 5.7). В третьем разделе используется аутентификация из коробки + функционал подтверждения регистрации, также из коробки (с версии 5.7).

Содержание:

  1. С использованием собственной аутентификации
  2. С использованием аутентификации из коробки
  3. E-mail подтверждение регистрации из коробки в Laravel 5.7

С использованием собственной аутентификации

Суть проекта такова: пользователь заполняет форму регистрации, после чего пользовательские данные заносятся в БД. Но сразу после этого пользователь не сможет зайти под своим именем на сайт, так как сначала он должен пройти проверку подлинности своего почтового ящика. Для осуществлении такой проверки, кроме стандартных полей в таблицу users (name, email, password) мы добавим 2 дполнительных поля: verified и token. Первое поле может принимать значения true/false (изначально false), второе поле служит для хранения случайного значения – ключа. На свой почтовый ящик пользователь получает сообщение со ссылкой, содержащей этот ключ из базы. После того как пользователь переходит по ссылке, ключ из ссылки и ключ из базы сравниваются, при их совпадении поле verified переходит в состояние true, а ключ удаляется. Активация считается завершенной. После этого пользователь сможет успешно пройти аутентификацию. Для работы с БД нам потребуется изменить стандартный файл миграции 2014_10_12_000000_create_users_table.php, добавим в него необходимые поля: verified и token. После чего содержимое метода up() будет таким:
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password', 60);
    $table->boolean('verified')->default(false);
    $table->string('token')->nullable();
    $table->rememberToken();
    $table->timestamps();
});
Перейдем в файл маршрутов (web.php). Создадим:
  1. маршруты (post и get) для регистрации и авторизации;
  2. маршрут для проверки ключа, полученного пользователем в письме, отправленном ему после регистрации;
  3. маршрут для выхода (logout) со страницы администратора (dashboard) и для входа на нее.
Готовый файл будет таким:
Route::get('/', function () {
    return view('welcome');
});

Route::get('register', 'RegistrationController@register');
Route::post('register', 'RegistrationController@postRegister');

Route::get('register/confirm/{token}', 'RegistrationController@confirmEmail');

Route::get('login', 'SessionsController@login')->middleware('guest');
Route::post('login', 'SessionsController@postLogin')->middleware('guest');
Route::get('logout', 'SessionsController@logout');

Route::get('dashboard', ['middleware' => 'auth', function() {
    return 'Добро пожаловать, '.Auth::user()->name.'!';
}]); 
Далее создадим первый контроллер RegistrationController. В него добавим метод confirmEmail(), который подтверждает введенный пользователем почтовый адрес:
public function confirmEmail(Request $request, $token)
{
    User::whereToken($token)->firstOrFail()->confirmEmail();

    $request->session()->flash('message', 'Учетная запись подтверждена. Войдите под своим именем.');

    return redirect('login');
}
Как вы могли заметить по файлу маршрутов, этот контроллер содержит еще два метода: register() и postRegister(). Первый отвечает за генерацию формы регистрации:
public function register()
{
    return view('auth.register');
}
Второй за проверку данных из этой формы, заполненной пользователем:
public function postRegister(Request $request)
{
    $this->validate($request, [
        'name' => 'required',
        'email' => 'required|email|unique:users',
        'password' => 'required'
    ]);

    $user = User::create($request->all());

    Mail::to($user)->send(new UserRegistered($user));

    $request->session()->flash('message', 'На ваш адрес было выслано письмо с подтверждением регистрации.');

    return redirect()->back();
}
В конструкторе контроллера вызовем middleware:
public function __construct()
{
    $this->middleware('guest');
}
Также не забудьте в заголовке контроллера добавить нужные строчки для классов UserRegistered и Mail. В результате чего заголовок должен выглядеть следующим образом:
namespace App\Http\Controllers;

use App\User;
use App\Mail\UserRegistered;
use Illuminate\Support\Facades\Mail;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
Второй из нужных нам контроллеров, это SessionsController. В нем создадим 5 методов. Первый метод – это метод с формой для входа:
public function login()
{
    return view('auth.login');
}
Второй для обработки данных с этой формы:
public function postLogin(Request $request)
{
    $this->validate($request, ['email' => 'required|email', 'password' => 'required']);

    if ($this->signIn($request)) {
        $request->session()->flash('message', 'Добро пожаловать!');

        return redirect()->intended('dashboard');
    }

    $request->session()->flash('message', 'Вход запрещен!');

    return redirect()->back();
}
Третий для выхода (logout):
public function logout(Request $request)
{
    Auth::logout();

    $request->session()->flash('message', 'Вы разлогинились.');

    return redirect('login');
}
Четвертый и пятый для проверки данных из формы (используются во втором методе):
protected function signIn(Request $request)
{
    return Auth::attempt($this->getCredentials($request), $request->has('remember'));
}
protected function getCredentials(Request $request)
{
    return [
        'email'    => $request->input('email'),
        'password' => $request->input('password'),
        'verified' => true
    ];
}
В первом контроллере RegistrationController есть строчка:
Mail::to($user)->send(new UserRegistered($user));
С помощью нее мы отправляем письмо пользователю после заполнения формы регистрации. Начиная с версии 5.3 для отправки писем можно воспользоваться классом Mailable. Подробнее об отправке писем можно почитать в документации, в разделе Mail. Чтобы создать свой mailable-класс (в нашем случае класс с именем UserRegistered) нужно выполнить команду:
php artisan make:mail UserRegistered
После чего в директории проекта появится новая папка Mail, а в ней файл UserRegistered.php, с mailable-классом. Для нашего проекта содержимое класса UserRegistered будет следующим:
use Queueable, SerializesModels;

public $user;

public function __construct(User $user)
{
    $this->user = $user;
}

public function build()
{
    return $this->from('admin@site.com')
            ->view('emails.confirm');
}
В методе build() мы используем вид confirm.blade.php, в котором содержится структура письма. Структура может быть такая:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Активация регистрации нового ползователя</title>
</head>
<body>
    <h1>Спасибо за регистрацию, {{$user->name}}!</h1>

    <p>
        Перейдите <a href='{{ url("register/confirm/{$user->token}") }}'>по ссылке </a>чтобы завершить регистрацию!
    </p>
</body>
</html>
На этапе разработки для получения писем можно воспользоваться файлом laravel.log. Для этого в файле .env в строчке MAIL_DRIVER нужно указать log.
Переходим к модели User. В модели нам потребуется три метода. Первый – это boot()-метод, который выполняется при загрузке модели. С помощью него мы создаем ключ подтверждения, отправляемый пользователю. Необходимый метод будет выглядеть следующим образом:
public static function boot()
{
    parent::boot();

    static::creating(function ($user) {
        $user->token = str_random(30);
    });
}
Во втором методе мы хэшируем пароль пользователя:
public function setPasswordAttribute($password)
{
    $this->attributes['password'] = bcrypt($password);
}
В третьем методе, при успешной валидации пользователя мы удаляем ключ из базы и задаем статус поля verified равным true:
public function confirmEmail()
{
    $this->verified = true;
    $this->token = null;

    $this->save();
}
Осталось создать виды. Напоминаю, что для письма вид уже был создан. Основной вид приложения (используется Bootstrap):
<html>
<head>
    <meta charset="UTF-8">
    <title>E-mail активация</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        @include('flash')

        @yield('content')
    </div>
</body>
</html>
В этом виде используется вложенный вид flash для вывода сообщений:
@if (session()->has('message'))
    <div class="alert alert-info">{{ session('message') }}</div>
@endif
Вид с формой для регистрации:
@extends('app')

@section('content')
<h1>Регистрация</h1>

@include('errors')

<form method="POST" action='{{ url("register/") }}'>
    {!! csrf_field() !!}

    <div class="form-group">
        <label for="name">Имя:</label>
        <input type="text" name="name" id="name" class="form-control" value="{{ old('name') }}">
    </div>

    <div class="form-group">
        <label for="email">Email:</label>
        <input type="text" name="email" id="email" class="form-control" value="{{ old('email') }}">
    </div>

    <div class="form-group">
        <label for="password">Пароль:</label>
        <input type="password" name="password" id="password" class="form-control">
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-default">Зарегистрироваться</button>
    </div>
    </form>
@stop
Вид с формой для входа на сайт:
@extends('app')

@section('content')
    <h1>Авторизация</h1>

    @include('errors')

    <form method="POST" action='{{ url("login/") }}'>
        {{csrf_field()}}

        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" name="email" id="email" class="form-control" value="{{ old('email') }}">
        </div>

        <div class="form-group">
            <label for="password">Пароль:</label>
            <input type="password" name="password" id="password" class="form-control">
        </div>

        <div class="checkbox">
            <label>
                <input type="checkbox" name="remember" id="remember" {{ old('remember') ? ' checked' : '' }}> Запомнить меня
            </label>
        </div>

        <div class="form-group">
            <button type="submit" class="btn btn-default">Войти</button>
        </div>
    </form>
@stop
Оба вида (регистрации и авторизации) используют вложенный вид errors:
@if (count($errors) > 0)
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
К содержанию

Оставьте свой комментарий

Комментарии