為了密碼垃圾使用者,一般在使用者註冊的時候都會對使用者進行驗證。這裡我們在註冊的時候填寫了使用者的郵箱,但在註冊過程中並沒有對使用者郵箱的真實性進行驗證,因此需要新增一個郵件驗證機制。
整體思路是使用者註冊的時候,向使用者的郵箱傳送一個帶有特殊驗證串的連結,使用者點選連結之後,使用者驗證通過,然後就可以正常登入的,否則使用者登入的時候提示使用者需要郵件進行啟用。
修改使用者資料表
為了實現上面的功能,需要在使用者表中新增兩個欄位,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
這樣,所有需要的工作都做完了,註冊賬號可以看到郵箱中有啟用郵件
同時介面上顯示提示內容:
啟用使用者
使用者註冊成功,收到郵件之後,需要通過點選連結啟用使用者。上面我們已經新增了路由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
對於任何無效的連結(無效,過期,或者已經啟用的)都提示啟用失敗,請重新註冊。
限制未啟用使用者的登入
到目前為止,我們都是在修改註冊時候的邏輯。但是不要忘了,之前的登入邏輯是沒有驗證使用者郵箱是否啟用。因此在使用者登入的時候需要新增對使用者是否啟用邏輯的驗證。
使用者登入的控制器為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')
);
}
這樣我們就限制了只有啟用的使用者才能登入。