メールのみを使用してLaravelでパスワードレス認証を作成する

私は最近、問題の1つがユーザーのパスワードであるプロジェクトに取り組みました。 管理者はアプリケーションにユーザーを追加したため、パスワードがありません。また、登録後の最初のログインでパスワードを考えさせることは非常に不便でした。

そこで、パスワードなしのログイン方法を試すことにしました。 これを使用する機会がなかった場合、その仕組みを説明します。

ログインページで、ユーザーは自分の電子メールアドレスを入力します。このアドレスにログインへのリンクが表示されます。 各ユーザーログインのリンクは一意であるため、リンクをたどると、パスワードを入力しなくてもユーザーのIDが確認されます。

作成を始めましょう!

画像


新しいアプリケーションとmake:auth


最初に、認証を接続してアプリケーションを作成します。

laravel new medium-login cd medium-login php artisan make:auth 


これで、ビューを含む承認に必要なすべてのファイルができました。 それらから始めましょう。

ログインおよび登録ページの変更


もちろん、ユーザー名とパスワードを組み合わせるのはかなり良い考えですが、両方のフォームでパスワードフィールドを放棄する必要があります。

ファイル `resources / views / auth / login.blade.php`を開き、パスワード(ラベル、入力、ラッパー)の入力を担当するグループを削除します。 保存して閉じます。

ファイル `resources / views / auth / register.blade.php`を開き、パスワード(` password`)とパスワード確認( `password-reset`)の入力を担当するグループを削除します。 保存して閉じます。

後で、認証ページでログイン方法に関する指示を追加したり、パスワードをリセットするためのリンクを投稿したりできますが、これは後で行われます。

登録ルートを変更する


そのため、エントリポイントと登録ポイントを指すルートを変更する必要があります。 「AuthController」コントローラーを見てください。

まず、パスワードフィールドの検証を返す `validator`メソッドに注目します。 彼はアカウントの登録プロセスを担当しているため、パスワードへのバインドを取り除く必要があります。

最終的に、関数は次のようになります。

 // app/http/Controllers/Auth/AuthController.php protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users', ]); } 


`Create`メソッドに対しても同じことを行い、フォームにそれをもたらします:

 // app/http/Controllers/Auth/AuthController.php protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], ]); } 


ログインパスの重複


ご覧のとおり、ユーザーを登録する方法はありません。 これらは、 `AuthenticatesUsers`認証特性と` RegistersUsers`登録特性を使用する `AuthenticatesAndRegistersUsers`トレイに隠されています。 `AuthenticatesUsers`トレイトに移動して、ファイルの最後で` login`という名前のユーザー認証メソッドを見つけることができます。

そこに起こるすべては安全なパスワードに基づいていますが、この方法は置き換えることができます...

新しい方法の目的は、ユーザーのメールアドレスにログインリンクを送信することです。 `AuthController`コントローラーに戻って、AuthenticatesUsersの` login`をオーバーライドするログインメソッドを追加しましょう。

 // app/http/Controllers/Auth/AuthController.php public function login(Request $request) { // validate that this is a real email address // send off a login email // show the users a view saying "check your email" } 


メール確認


登録ユーザーの電子メールアドレスの現実を確認するのは非常に簡単です。

 $this->validate($request, ['email' => 'required|email|exists:users']); 


メール送信


次に、ユーザーに入り口へのリンクを送信する必要があります。 少し時間がかかります。

電子メールトークンの形成と検証のための構造の作成


データベース構造 `password_reset`の形式に精通している場合、より簡単になります。 同様のものを作成します。 誰かがシステムにログインしようとするたびに、テーブルにエントリを追加する必要があります。これは、電子メールで送信された電子メールアドレスと一意のトークンをURLとして記録し、エントリの作成日と有効期間を記録します。

最後に、URLを使用して作成(および検証)します。たとえば、「myapp.com / auth / email-authenticate / 09ajfpoib23li4ub123p984h1234`」です。 トークンの寿命は限られているため、このURLを特定のユーザーに関連付け、メール、トークン、および各テーブルエントリの作成日を追跡する必要があります。

だから、彼のための移行を作成します。

 php artisan make:migration create_email_logins_table --create=email_logins 


そして、いくつかのフィールドを追加します。

 Schema::create('email_logins', function (Blueprint $table) { $table->string('email')->index(); $table->string('token')->index(); $table->timestamps(); }); 


注:必要に応じて、トークンの代わりに「id」列の値を使用できますが、より良いオプションにはいくつかの理由があります。 いずれにせよ、あなたが決める。


それでは、モデルを作成しましょう。

 php artisan make:model EmailLogin 


ファイル( `app / EmailLogin.php`)を編集し、目的のプロパティを持つインスタンスを作成することで簡単にします:

 class EmailLogin extends Model { public $fillable = ['email', 'token']; } 


また、ユーザーを検索する場合は、識別子ではなくメールを使用して、メールの列を手動でリンクする必要があります。

 class EmailLogin extends Model { public $fillable = ['email', 'token']; public function user() { return $this->hasOne(\App\User::class, 'email', 'email'); } } 


トークン作成


これで、電子メールメッセージを作成する準備ができました。 事前に生成された一意のトークンを含むURLを使用します。

トークンを作成して保存する方法を理解する必要があります。 これを行うには、 `EmailLogin`のインスタンスを作成する必要があるため、始めましょう:

 public function login() { $this->validate($request, ['email' => 'required|email|exists:users']); $emailLogin = EmailLogin::createForEmail($request->input('email')); } 


このメソッドを `EmailLogin`に追加しましょう:

 class EmailLogin extends Model { ... public static function createForEmail($email) { return self::create([ 'email' => $email, 'token' => str_random(20) ]); } } 


ランダムトークンを生成し、 `EmailToken`クラスのインスタンスを作成して、それを受け取ります。

電子メールで送信するためのURLの形成


そのため、ユーザーにメッセージを送信する前に、「EmailToken」を使用してURLを生成する必要があります。

 public function login() { $this->validate($request, ['email' => 'required|email|exists:users']); $emailLogin = EmailLogin::createForEmail($request->input('email')); $url = route('auth.email-authenticate', [ 'token' => $emailLogin->token ]); } 


それのためのルートを作成しましょう:

 // app/Http/routes.php Route::get('auth/email-authenticate/{token}', [ 'as' => 'auth.email-authenticate', 'uses' => 'Auth\AuthController@authenticateEmail' ]); 


...そして、このルートが機能するようにコントローラーにメソッドを追加します。

 class AuthController { ... public function authenticateEmail($token) { $emailLogin = EmailLogin::validFromToken($token); Auth::login($emailLogin->user); return redirect('home'); } } 


...そして、トークンを検証するための `validFromToken`メソッドを追加します:

 class EmailLogin { ... public static function validFromToken($token) { return self::where('token', $token) ->where('created_at', '>', Carbon::parse('-15 minutes')) ->firstOrFail(); } 


これで、各トークンの関連性を考慮して、着信ルートが作成されました。 トークンが関連する場合、ユーザーはアドレス「mysite.ru / home」にリダイレクトされます。

さて、メールを送信しましょう。

手紙を送る


コントローラにcall call callを追加します。

 public function login() { ... Mail::send('auth.emails.email-login', ['url' => $url], function ($m) use ($request) { $m->from('noreply@myapp.com', 'MyApp'); $m->to($request->input('email'))->subject('MyApp Login'); }); 


...そしてテンプレートを作成します:

 <!-- resources/views/auth/emails/email-login.blade.php --> Log in to MyApp here: <a href="{{ $url }}">{{ $url }}</a> 


返却テンプレート


テンプレートは任意の便利な方法で設計できますが、テキストを使用するだけです。「おい、それを確認するために石鹸を送った。 それがすべてです。」

 return 'Login email sent. Go check your email.'; 


共同エントランス


私たちのシステムを見てください。 `AuthController`コントローラーに新しい` login`メソッドがあります:

 public function login(Request $request) { $this->validate($request, ['email' => 'required|exists:users']); $emailLogin = EmailLogin::createForEmail($request->input('email')); $url = route('auth.email-authenticate', [ 'token' => $emailLogin->token ]); Mail::send('auth.emails.email-login', ['url' => $url], function ($m) use ($request) { $m->from('noreply@myapp.com', 'MyApp'); $m->to($request->input('email'))->subject('MyApp login'); }); return 'Login email sent. Go check your email.'; } 


複数のビューを作成し、既存のビューを更新しました(それらのパスワードエントリを削除しました)。 また、 `/ auth / email-authenticate`に新しいルートを作成しました。 そして、彼らはすべての必要なクラスを持つ `EmailLogin`の移行も作成しました。

以上です!


そして...利益! コードにすべての例を入れて、完全に機能するパスワードなしのログインシステムを取得します。

ユーザーを登録するには、ユーザーのメールアドレスを見つけるだけです。 また、認証中は、メールアドレスに加えて、何かを覚えて入力する必要がなくなります。 これ以上パスワードを忘れません。 ブーム!

翻訳者から


記事を翻訳する際、ロシア語を話すユーザーが読みやすいように情報が適合されました。

Source: https://habr.com/ru/post/J279173/


All Articles