LoginSignup
12
16

More than 5 years have passed since last update.

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

Posted at

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
12
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
16