Laravel5.8 入門系列三,新增註冊郵箱驗證

寫PHP的老王發表於2019-09-08

為了密碼垃圾使用者,一般在使用者註冊的時候都會對使用者進行驗證。這裡我們在註冊的時候填寫了使用者的郵箱,但在註冊過程中並沒有對使用者郵箱的真實性進行驗證,因此需要新增一個郵件驗證機制。

整體思路是使用者註冊的時候,向使用者的郵箱傳送一個帶有特殊驗證串的連結,使用者點選連結之後,使用者驗證通過,然後就可以正常登入的,否則使用者登入的時候提示使用者需要郵件進行啟用。

修改使用者資料表

為了實現上面的功能,需要在使用者表中新增兩個欄位,activity_token,activity_expire,is_activity分別表示啟用字串,啟用驗證過期時間,是否啟用標記。

對於資料庫的修改,可以使用Laravel建立資料遷移檔案,並執行資料遷移完成。

在根目錄下,執行下面的命令,建立一個對users表的資料庫遷移檔案

php artisan make:migration alter_users_table --table=users

上面的命令會在database/migrations目錄下新增一個類似2019_09_08_082359_alter_users_table.php的檔名,前面是日期加一個隨機數。

修改你的資料庫遷移檔案,修改up方法如下:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('activity_token')->comment('啟用驗證token');
        $table->dateTime('activity_expire')->comment('啟用過期時間');
        $table->tinyInteger('is_activity')->default(0)->comment('是否啟用1是,0否');
    });
}

執行資料庫遷移命令php artisan migrate

插入使用者資料新增啟用token,啟用過期時間

使用者註冊的控制器的檔案為app\Http\Controller\Auth\RegisterController.php
所有的業務邏輯,都是通過Illuminate\Foundation\Auth\RegistersUsers這個trait實現的。到目前為止,這個檔案沒有太多的內容,基本上都是Laravel本身就已經完成了大部分邏輯。

修改RegisterController中的create方法,新增activity_token,email_verified_at的賦值邏輯。

//注意需要新增 use Illuminate\Support\Facades\Date; 
protected function create(array $data)
{
    return User::create([
        'activity_token'=>\Str::random(60),
        'activity_expire'=>Date::now('+1 days'),
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
    ]);
}

注意,這裡我們只是把資料設定進去了,還要保證模型中這兩個欄位是允許填充的。修改app\User.php檔案,在$fillable屬性陣列中新增activity_token,email_verified_at兩個欄位。修改後內容如下:

protected $fillable = [
    'name', 'email', 'password','activity_token','activity_expire'
];

這樣,我們就把我們的啟用串,以及啟用過期時間設定到註冊使用者表中去了。趕緊去嘗試註冊一個新使用者,看看資料表中是否有了activity_token資料了。

給使用者郵箱傳送郵件

我們期望的是在使用者資料儲存到資料庫之後,向使用者郵箱傳送一封驗證郵件,然後跳轉到一個頁面提示使用者去郵箱啟用。

Laravel的郵箱配置檔案在config/mail.php中。這裡我們還是通過修改本地環境變數修改郵箱配置。修改環境變數下面的內容:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io  ## smtp地址,qq 地址為 smtp.qq.com
MAIL_PORT=2525   ## smtp埠,qq 462
MAIL_USERNAME=null  ## 郵箱名,qq 自己郵箱地址
MAIL_PASSWORD=null  ## 密碼,qq郵箱需要開通smtp後的臨時碼
MAIL_ENCRYPTION=null  ## 如果服務商加密方式是SSL,比如qq,填寫SSL

為了實現註冊傳送郵件功能更,我們需要覆蓋register方法。在RegisterController.php中新增以下方法,內容如下:

public function register(Request $request)
{
    $this->validator($request->all())->validate();
    event(new Registered($user = $this->create($request->all())));
    //傳送郵件
    \Mail::raw(
    '請在'.$user->activity_expire.'前,點選連結啟用您的賬號'.route('user.activity',['token'=>$user->activity_token])
    ,function($message) use($user){
        $message->from('1035308417@qq.com','老王Laravel入門')
        ->subject('註冊啟用郵件')
        ->to($user->email);
    });
    //顯示註冊啟用提示資訊
    return view('auth.registed',['user'=>$user]);
}

上面的內容需一個啟用連結路由,我們先直接在路由檔案中隨便新增。在路由檔案route/web.php總新增啟用路由:

Route::get('activity/{token}','Auth\RegisterController@activity')->name('user.activity');

新增一個提示資訊的試圖檔案resource/views/auth/registed.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>

                <div class="card-body">
                    啟用連結已傳送至您的郵箱{{$user->email}},請於{{$user->activity_expire}}前啟用您的賬戶。
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

這樣,所有需要的工作都做完了,註冊賬號可以看到郵箱中有啟用郵件
Laravel

同時介面上顯示提示內容:
Laravel

啟用使用者

使用者註冊成功,收到郵件之後,需要通過點選連結啟用使用者。上面我們已經新增了路由user.activity。所以只需要在RegisterController中新增activity方法,通過token驗證使用者,同時在activityres試圖檔案上提示使用者啟用結果。


function activity($token){
    $user = User::find(['activity_token'=>$token]);
    $res = false;
    if($user && strtotime($user->activity_expire)>time())
    {
        $user->is_activity = 1;
        $res = $user->save();
    }
    return view('auth.activityres',['res'=>$res]);
}

試圖檔案resources/views/auth/activityres.blade.php內容如下:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Activity Result') }}</div>

                <div class="card-body">
                    @if($res === false)
                        該連結已失效,請重新<a href="{{route('register')}}">註冊>></a>
                    @else
                        您的賬號已經啟用,請<a href="{{route('login')}}">登入>></a>
                    @endif
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

對於任何無效的連結(無效,過期,或者已經啟用的)都提示啟用失敗,請重新註冊。

Laravel

限制未啟用使用者的登入

到目前為止,我們都是在修改註冊時候的邏輯。但是不要忘了,之前的登入邏輯是沒有驗證使用者郵箱是否啟用。因此在使用者登入的時候需要新增對使用者是否啟用邏輯的驗證。

使用者登入的控制器為app\Http\Controller\Auth\LoginController,其中,主要的業務邏輯由Illuminate\Foundation\Auth\AuthenticatesUsers 這個trait實現。我們需要在嘗試登入的時候新增使用者是否啟用的判斷條件,因此我們複製AuthenticatesUsers中的attempLogin方法到LoginController中。修改內容如下:

/**
 * Attempt to log the user into the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function attemptLogin(Request $request)
{
    return $this->guard()->attempt(
        [
            'email'=>$request->email,
            'password'=>$request->password,
            'is_activity'=>1,
        ], $request->filled('remember')
    );
}

這樣我們就限制了只有啟用的使用者才能登入。

Laravel

寫PHP的老王

相關文章