Laravelで認証用の仕組みの作り方

※自分用メモ

■Laravelで認証用の仕組みの作り方
	※前提条件
		・認証テーブルには最低下記のカラムが必要
			login_id(名前は任意だがデフォルトはemail)
			password(名前は任意だがデフォルトはpassword。保存時にbcryptで暗号化させないと認証できない。)
			remember_token(プログラムの修正で消すことも可能！？)

			+して平パスワードを保存する場合カラムを追加
			password_raw(名前は任意)

		・ログイン画面のフォーム属性ユーザーID・パスワードのnameの値と認証用テーブルのユーザーID・パスワードのカラム名は同じにしないとエラーになる
			例：
				・ログイン画面フォーム属性
					ユーザーIDのname：login_id
					パスワードのname：password

				認証用テーブルusersのカラム
					ユーザーIDのカラム名：login_id
					パスワードのカラム名：password


	・元になる認証の仕組みがある場合
		１．元になる認証用のディレクトリをコピーし複製を作成
			例：競馬サイトの場合
				コピー元：/data/www/jray/app/Http/Controllers/Auth
				コピー先：/data/www/jray/app/Http/Controllers/Agency/Auth

		２．認証用のMiddlewareをコピーし複製を作成
			例：競馬サイトの場合
				コピー元：/data/www/jray/app/Http/Middleware/MemberAuthToken.php
				コピー先：/data/www/jray/app/Http/Middleware/AgencyMemberAuthToken.php

		３．２で作成したMiddlewareをKernel.phpに登録する
			/data/www/jray/app/Http/Kernel.php
				例：競馬サイトの場合
					protected $routeMiddlewareの配列内、下記のように追加する
					'auth.token' => \App\Http\Middleware\MemberAuthToken::class,
					'auth.admin.token' => \App\Http\Middleware\MemberAuthToken::class,
					'auth.agency.token' => \App\Http\Middleware\AgencyMemberAuthToken::class,

				routes/web.php
				認証をかけたいルーティングを下記に書く
				Route::group(['middleware' => 'auth.agency.token'], function() {
					認証後ページのルーティングをここに書く
				});

		４．認証に使用するテーブルのModelを修正
			例：競馬サイトの場合
				/data/www/jray/app/Model/
				修正前：
					use Illuminate\Database\Eloquent\Model;

					class Agency extends Model{

				修正後：
					use Illuminate\Notifications\Notifiable;
					use Illuminate\Foundation\Auth\User as Authenticatable;

					class Agency extends Authenticatable {

		５．２で作成したファイル内のAuth::guard('user')部分を今回の認証用に合わせ、その他も今回に合わせて修正
			例：競馬サイトの場合
					修正前：Auth::guard('user')
					修正後：Auth::guard('agency')

		６．LoginController.phpを今回に合わせて修正
			下記のemailはログイン画面のユーザーIDのフォーム部分と認証用テーブルにあたるため、今回のに変更
			例：競馬サイトの場合
				ログイン画面のユーザーIDのフォームのname=login_id、認証用テーブルのユーザーIDのカラム名がlogin_idなら下記になる。
				passwordの部分も変更する場合は
				public function username()
				{
					return 'login_id';
				}

				下記も今回のに変更
				修正前：Auth::guard('user')
				修正後：Auth::guard('agency')
				protected function guard()
				{
					return Auth::guard('agency');
				}

		７．RegisterController.phpを今回に合わせて修正
		８．viewファイルもコピーし修正
		９．config/app.phpを修正
			例：競馬サイトの場合
			'guards' => [
				'user' => [
					'driver' => 'session',
					'provider' => 'user',
				],
				'admin' => [
					'driver' => 'session',
					'provider' => 'admin',
				],
				'agency' => [
					'driver' => 'session',
					'provider' => 'agency',
				],
			],

			'providers' => [
				'user' => [
					'driver' => 'eloquent',
					'model' => App\Model\User::class,
				],
				'admin' => [
					'driver' => 'eloquent',
					'model' => App\Model\Admin::class,
				],
				'agency' => [
					'driver' => 'eloquent',
					'model' => App\Model\Agency::class,
				],
			],

			'passwords' => [
				'user' => [
					'provider' => 'user',
					'table' => 'password_resets',
					'expire' => 129600,
				],
				'admin' => [
					'provider' => 'admin',
					'table' => 'password_resets',
					'expire' => 180,
				],
				'agency' => [
					'provider' => 'agency',
					'table' => 'password_resets',
					'expire' => 180,
				],
			],



	・元になる認証の仕組みがない場合
		※参考URL：https://readouble.com/laravel/5.5/ja/authentication.html

		１．php artisan make:auth
			実行すると認証に必要なファイルが生成される
				resources/views/auth
				app/Http/Controllers/Auth
					RegisterController.php
					LoginController.php
					ForgotPasswordController.php
					ResetPasswordController.php

		２．必要に応じてLoginController.php内にメソッドをオーバーライドする
			修正が必要になる可能性のあるメソッド

			//AuthenticatesUsersのloginのメソッドをadmin用にオーバーライド
			public function login(Request $request)
			{
				$this->validateLogin($request);

				if ($this->hasTooManyLoginAttempts($request)) {
					$this->fireLockoutEvent($request);

					return $this->sendLockoutResponse($request);
				}

				if ($this->attemptLogin($request)) {
					//ログ出力
					$this->log_obj->addLog(config('const.admin_display_list')['login'].",{$request->input('email')}");
					
					//ログイン成功時にホスト名とユーザーエージェントをadminsテーブルにupdate
					// add by nishizawa date 2017.9.13
					$update = Admin::where('email', $request->input('email'))
						->update([
							'access_host'		=> $_SERVER['SERVER_NAME'],
							'user_agent'		=> $_SERVER['HTTP_USER_AGENT'],
							'last_login_date'	=> Carbon::now(),
						]);
					
					return $this->sendLoginResponse($request);
				}

				$this->incrementLoginAttempts($request);

				return $this->sendFailedLoginResponse($request);
			}
			
			//AuthenticatesUsersのvalidateLoginのメソッドをadmin用にオーバーライド
			protected function validateLogin(Request $request)
			{
				$this->validate($request, [
					$this->username() => 'bail|required|string|exists:admins|check_approved',
					'password' => 'bail|required|string',
				]);
			}
			
			//AuthenticatesUsersのcredentialsのメソッドをadmin用にオーバーライド
			protected function credentials(Request $request)
			{
				//オリジナルコード
				return $request->only($this->username(), 'password');
			}

			//AuthenticatesUsersのcredentialsのメソッドをadmin用にオーバーライド
			public function logout()
			{
				$user = Utility::getAdminDefaultDispParam();

				//情報が取得できていなかったら(セッションが切れていたら)
				if( empty($user) ){
					//管理画面のログイン前ページへリダイレクト
					return redirect('/admin/login');
				}

				//ログ出力
				$this->log_obj->addLog(config('const.admin_display_list')['logout'].",{$user['login_id']}");

				//セッションを破棄(検索条件)
				Session::flush();

				$this->guard()->logout();

				//管理画面のログイン前ページへリダイレクト
				return redirect('/admin/login');
			}

			//AuthenticatesUsersのcredentialsのメソッドをadmin用にオーバーライド
			protected function guard()
			{
				return Auth::guard('admin');
			}

			//AuthenticatesUsersのcredentialsのメソッドをadmin用にオーバーライド
			//return 'email'の部分がログイン画面のユーザーIDのフォーム名、認証用テーブルのユーザーIDにあたるカラム名になっている
			public function username()
			{
				return 'email';
			}

		３．２と同様に必要があれば下記のファイルを修正
				app/Http/Controllers/Auth
					RegisterController.php
					ForgotPasswordController.php
					ResetPasswordController.php

		４．config/app.phpを修正
			例：競馬サイトの場合
			'guards' => [
				//ユーザー側
				'user' => [
					'driver' => 'session',
					'provider' => 'user',
				],
				//管理側
				'admin' => [
					'driver' => 'session',
					'provider' => 'admin',
				],
				//代理店管理側
				'agency' => [
					'driver' => 'session',
					'provider' => 'agency',
				],
			],

			'providers' => [
				'user' => [
					'driver' => 'eloquent',
					'model' => App\Model\User::class,
				],
				'admin' => [
					'driver' => 'eloquent',
					'model' => App\Model\Admin::class,
				],
				'agency' => [
					'driver' => 'eloquent',
					'model' => App\Model\Agency::class,
				],
			],

			'passwords' => [
				'user' => [
					'provider' => 'user',
					'table' => 'password_resets',
					'expire' => 129600,
				],
				'admin' => [
					'provider' => 'admin',
					'table' => 'password_resets',
					'expire' => 180,
				],
				'agency' => [
					'provider' => 'agency',
					'table' => 'password_resets',
					'expire' => 180,
				],
			],