Posted at

Laravel5.4 ユーザー登録時にメールアドレス認証を入れる

More than 1 year has passed since last update.

Authにはユーザー登録時のメールアドレス認証がないので入れてみる。


.evn編集

デフォルトでsmtpになっているのでsendmailに変更しておく。


.env

MAIL_DRIVER=sendmail

...

MAIL_FROM_ADDRESS=noreply@example.com #追加
MAIL_FROM_NAME=hoge #追加



ユーザーテーブルに項目追加


database/migrations/2014_10_12_000000_create_users_table.php

    public function up()

{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->string('email_token')->nullable(); #追加
$table->tinyInteger('verified')->default(0); #追加
$table->tinyInteger('status')->default(0); #追加
$table->timestamps();
});
}

再構築

php artisan migrate:refresh


ユーザーモデルの編集


app/User.php

    protected $fillable = [

'name', 'email', 'password', 'email_token', 'verified'
];

...

/**
* メール認証が完了したら更新
*/
public function verified()
{
$this->email_token = null;
$this->verified = 1;
$this->status = 1;
$this->save();
}



メール認証クラスの作成

artisanコマンドで作成

php artisan make:mail EmailVerification

ユーザーモデルを追加する


app/Mail/EmailVerification.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;

class EmailVerification.php extends Mailable
{
use Queueable, SerializesModels;

public $user;

/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}

/**
* Build the message.
*
* @return $this
*/
public function build()
{
// メールのタイトルもここで変更
return $this->subject('メールアドレスの登録確認')
->view('email.verification');
}
}



メールビューの作成


resources/views/emails/verification.blade.php

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" rel="stylesheet" media="all">
/* Media Queries */
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>
<?php
$style = [
/* Layout ------------------------------ */
'body' => 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;',
'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6;',
/* Masthead ----------------------- */
'email-masthead' => 'padding: 25px 0; text-align: center;',
'email-masthead_name' => 'font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;',
'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF;',
'email-body_inner' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0;',
'email-body_cell' => 'padding: 35px;',
'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;',
'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;',
/* Body ------------------------------ */
'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;',
'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;',
/* Type ------------------------------ */
'anchor' => 'color: #3869D4;',
'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;',
'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;',
'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;',
'paragraph-center' => 'text-align: center;',
/* Buttons ------------------------------ */
'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px;
background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px;
text-align: center; text-decoration: none; -webkit-text-size-adjust: none;'
,
'button--green' => 'background-color: #22BC66;',
'button--red' => 'background-color: #dc4d2f;',
'button--blue' => 'background-color: #3869D4;',
];
?>

<?php $fontFamily = 'font-family: Arial, \'Helvetica Neue\', Helvetica, sans-serif;'; ?>

<body style="{{ $style['body'] }}">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $style['email-wrapper'] }}" align="center">
<table width="100%" cellpadding="0" cellspacing="0">
<!-- Logo -->
<tr>
<td style="{{ $style['email-masthead'] }}">
<a style="{{ $fontFamily }} {{ $style['email-masthead_name'] }}" href="{{ url('/') }}" target="_blank">
{{ config('app.name') }}
</a>
</td>
</tr>

<!-- Email Body -->
<tr>
<td style="{{ $style['email-body'] }}" width="100%">
<table style="{{ $style['email-body_inner'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-body_cell'] }}">
<!-- Greeting -->
<h1 style="{{ $style['header-1'] }}">
こんにちは、{{ $user->name }}さん
</h1>

<!-- Intro -->
<p style="{{ $style['paragraph'] }}">
以下のボタンをクリックして、メールアドレスの認証を行なってくださ>い。
</p>

<!-- Action Button -->
<table style="{{ $style['body_action'] }}" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<?php
$actionColor = 'button--blue';
?>

<a href="{{ url('register/verify/'.$user->email_token) }}"
style="{{ $fontFamily }} {{ $style['button'] }} {{ $style[$actionColor] }}"
class="button"
target="_blank">
認証する
</a>
</td>
</tr>
</table>

<!-- Outro -->
<p style="{{ $style['paragraph'] }}">
心当たりがない場合は、なにもせずにこのメールを削除してください。
</p>

<!-- Salutation -->
<p style="{{ $style['paragraph'] }}">
よろしくお願いします。
</p>
</td>
</tr>
</table>
</td>
</tr>

<!-- Footer -->
<tr>
<td>
<table style="{{ $style['email-footer'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-footer_cell'] }}">
<p style="{{ $style['paragraph-sub'] }}">
&copy; {{ date('Y') }}
<a style="{{ $style['anchor'] }}" href="{{ url('/') }}" target="_blank">{{ config('app.name') }}</a>.
All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>



Registerコントローラーの更新


app/Http/Controllers/Auth/RegisterController.php

<?php

...

use DB; //追加
use Mail; //追加
use Illuminate\Http\Request; //追加
use App\Mail\EmailVerification; //追加

...

protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'email_token' => str_random(10), //追加
]);
}

        // registerメソッドをオーバーライド
public function register(Request $request)
{
// validation
$validator = $this->validator($request->all());
if ($validator->fails())
{
$this->throwValidationException($request, $validator);
}

// DBトランザクションを利用する
DB::beginTransaction();
try
{
$user = $this->create($request->all());

// 名前とトークンはメールビューで利用しているのでパラメーターで渡す
$email = new EmailVerification(new User(['name' => $user->name, 'email_token' => $user->email_token]));
Mail::to($user->email)->send($email);
DB::commit();

$request->session()->flash('message', '入力したメールアドレス宛に「メールア
ドレスの登録確認」メールが届くので確認してね!'
);
return redirect('login');
}
catch(Exception $e)
{
// 失敗したらロールバック
DB::rollback();

$request->session()->flash('message', 'エラー!');
return redirect('login');
}
}

// メールアドレスの認証
public function verify($token)
{
User::where('email_token', $token)->firstOrFail()->verified();
request()->session()->flash('message', 'メールアドレスの登録確認が終わったよ!');
return redirect('login');
}



Registerビューにメッセージ表示

panel-bodyの後ろあたりに追加


resources/views/auth/register.blade.php

@if(Session::has('message'))

<div class="alert alert-info">{{Session::get('message')}}</div>
@endif


ルーティング追加

Auth::routes()の後ろあたりに追加


routes/web.php

Route::get('/register/verify/{token}', 'Auth\RegisterController@verify');



Loginコントローラーの修正


use Illuminate\Http\Request; //追加

...

/**
* credentialsメソッドをオーバーライド
* ログイン認証にstatusを追加する
*/
protected function credentials(Request $request)
{
return [
'email' => $request->email,
'password' => $request->password,
'status' => 1,
];
}


Loginビューにメッセージ表示

panel-bodyの後ろあたりに追加


resources/views/auth/login.blade.php

@if(Session::has('message'))

<div class="alert alert-info">{{Session::get('message')}}</div>
@endif