Laravelで独自の認証をしたいときに少々大変だったのでメモなどを。
*ディフォルトのテーブルはuserで認証項目もemailとpasswordと決まっています。
いじるところが色々ありまして、列挙すると以下のような感じでしょうか。
- 認証用のテーブルのモデルを作成
- 認証テーブルを読み込むようconfig/auth.phpを修正
- コントローラー内での認証処理
- ルーティングで呼び出しを設定
まずは「認証用のテーブルのモデルを作成」モデルの登録から。
ディフォルトだとUserというモデル(実際のテーブル名はusers)となっていますので、これをAdminにしたいとします。
と言ってもただのAdminモデルを使っても認証テーブルとしては機能せず、下記のように認証機能が備わっているモデルを継承する必要があります。
最小構成のAdmin.php。パスはApp/Model/Admin.phpです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App\Model; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable { protected $fillable = [ 'username', 'password', ]; } |
よく見るとUserにもこれがついていますね・・・
Laravel 5.3で認証関連機能のテーブル名を変更する方法
ちなみにfillableというのは更新系の処理で予期せぬ値が登録されることを防ぐための仕組みのようです。
【Laravel:Eloquentクラス】fillableとguardedの指定はどちらかだけでいい
次に「認証テーブルを読み込むようconfig/auth.phpを修正」のステップです。このモデルを読むようにconfig/auth.phpで設定変更をする必要があります。apiの記述をわざと抜いてます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'admins', //←ここをusersからadminsに変更 ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'admins'//←ここをusersからadminに変更 ] ], 'providers' => [ //usersを丸っと変更し、modelはクラスを登録。 'admins' => [ 'driver' => 'eloquent', 'model' => App\Model\Admin::class, ], ], ]; |
実際に「コントローラー内での認証処理」は下記のようになります。
app/Http/Controllers/Auth/LoginController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; use App\Model\Admin; class LoginController extends Controller { use AuthenticatesUsers; /** * Create a new controller instance. * * @return void */ public function __construct() { } //実際のログイン処理 public function login(Request $request) { $message = ''; if ($request->isMethod('post')) { $authinfo =[ 'username' => $request->username, 'password' => $request->password ]; //実際の認証ロジック if (Auth::attempt($authinfo)){ //成功時は認証がされているアクションに飛ぶ return redirect()->route('AdminHome'); } else { $message = 'ログインに失敗しました。'; } } return view('pc.admins.login',[ 'message' => $message ]); } |
設定をしたら「ルーティングで呼び出しを設定」をします。
1 2 3 4 5 6 7 8 9 |
//管理画面 Route::group(['prefix' => 'auth','middleware' => 'auth'], function () { Route::get('home', 'Auth\LoginController@index')->name('AdminHome'); }); Route::group(['prefix' => 'auth'], function () { Route::match(['get','post'],'login', 'Auth\LoginController@login')->name('login'); Route::get('logout', 'Auth\LoginController@logout')->name('logout'); }); |
ちなみにURL自体はprefixにauthが必須と言うわけではないのでを通常のURL内にmiddleware=>authだけを定義して認証状態をコントールできます。
また認証ページ(/auth/home)に認証なしにアクセスしようとすると飛ばすページを定義するには下記のように設定をします。
./app/Exceptions/Handler.php
1 2 3 4 5 6 7 8 |
protected function unauthenticated($request, AuthenticationException $exception) { if ($request->expectsJson()) { return response()->json(['error' => 'Unauthenticated.'], 401); } //認証が聞いていない場合に飛ばす先をここで定義 return redirect()->guest(route('login')); } |
この場合http://samle.com/auth/homeにアクセスしようとすると、このアクションはauthで認証が聞いているので、http://sample.com/auth/loginに飛ばされるようになります。
*まだ調査中ですが、非ログイン時にリダイレクトされるのは./app/HttpControllers/Auth内の他のファイル(例えばResetPasswordController.php)のredirectToの値で決まるようです。
ちなみに標準だとパスワードのハッシュ化にはbcryptというロジックで実装されます。
データベースに直でデータを入れたいときはbcrypt(‘生パスワード’)と加工してPHPから突っ込んであげれば大丈夫です。
1 2 |
//hogehogeをハッシュ化した値を取得したい時 echo bcrypt('hogehoge'); |
照合に関して
また入力した値がパスワードと一致するかは通常はAuthライブラリをそのまま使うので直接見ることはないかもしれませんが、何らかの用途で使う必要がある時は通常は下記のようにします。
1 2 3 4 5 6 7 8 9 |
use Hash //認証されたユーザーの取得 $user = Auth::user(); $input_password = '画面から入力したパスワード(ハッシュ化などはされていない値)' if (Hash::check($input_password, $user->password) { //パスワードが通った時 } |