【メモ】Laravel5.5で管理者用のログイン機能の実装


#やろうとしていること
Laravel5.5で標準ログイン機能と管理者ログイン機能を分けて実装。

#必要な作業
①.envファイルを修正
②config/auth.phpを修正
③config/session.phpの内容を修正
④web.phpを修正
⑤MiddlewareのRedirectfAuthenticcated.phpを修正
⑥app/Exception/Handler.phpを修正
⑦Adminフォルダーを作成して、既存のAuthからcontrollerをコピーして修正
　→HomeController.php
　→LoginController.php
⑧admin用のviewを追加
　→home.blade.php
　→index.blade.php
　→login.blade.php
⑨layoutsにapp_admin.blade.phpを追加
⑩Adminモデルを生成




##.envファイルを修正
ログインごとにセッションを分ける
[セッションについて](https://qiita.com/7968/items/ce03feb17c8eaa6e4672)
[Laravelでのセッションについて](https://reffect.co.jp/laravel/laravel-sessions-understand)
Cookieはクライアントに保存される情報のこと　 
サーバーからのレスポンスに「Cookieを保存しておいてください」という指示があった場合はクライアント側で保存しておく。そして随時通信するときにこんな情報をCookieで保存してるよーと伝えることができる。
ブラウザ側でSession IDを保存する場所がCookieとなり、サーバ側でSession IDを保持する場所がSessionになります。

```php
SESSION_COOKIE=auth
SESSION_COOKIE_ADMIN=auth-admin
```

##config/auth.phpを修正

```php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'user',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        'admins' => [
            'provider' => 'admins',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];
```

##config/session.phpの内容を一部追記

```php
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';

// 管理者側用セッション
if (strstr($uri, '/admin/') !== false || $uri === '/admin/login') {
	    $sessConf['cookie'] = env(
                 'SESSION_COOKIE_ADMIN',
	          str_slug(env('APP_NAME', 'laravel'), '_').'_admin_session'
							    );
}

return $sessConf;
```

##web.php

```php
Route::group(['prefix' => 'admin', 'middleware' => 'auth:admin'], function () {
    Route::post('logout', 'Admin\LoginController@logout')->name('admin.logout');
    Route::get('home', 'Admin\HomeController@index')->name('admin.home');
});

Route::group(['prefix' => 'admin'], function () {
    Route::get('login', 'Admin\LoginController@showLoginForm')->name('admin.login');
    Route::post('login', 'Admin\LoginController@login');
    Route::get('logout', function () {
        return abort(404);
    });
});
```

##MiddlewareのRedirectfAuthenticcated.phpを修正

```php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */

			public function handle($request, Closure $next, $guard = null) {
		$redir = '/home';
		switch ($guard) {
		case "admin":
			$redir = '/admin/home';
			break;
		default:
			$redir = '/home';
			break;
		}
		if (Auth::guard($guard)->check()) {
			return redirect($redir);
		}

		return $next($request);
	}

}
```

##app/Exception/Handler.phpを修正

```php
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }
		public function unauthenticated($request, AuthenticationException $exception) {
		if($request->expectsJson()) {
			return response()->json(['message' => $exception->getMessage()], 401);
		}

		if (in_array('admin', $exception->guards())) {
			return redirect()->guest(route('admin.login'));
		}

		return redirect()->guest(route('login'));
	}
}
```

##controllerのadminフォルダーを作成
###HomeControllerをコピー

```php
<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:admin');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('admin.home');
    }
		
}
```

###LoginController.phpをコピーしてAdminフォルダーの下に格納して修正

```php
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = 'admin/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin')->except('logout');
    }

		public function showLoginForm() {

		return view('admin.login');
	}

	protected function guard() {
		return Auth::guard('admin');
	}

	public function logout(request $request) {
		Auth::guard('admin')->logout();
		$request->session()->forget('login_admin');
		$request->session()->regenerate();

		return redirect('/admin/login');
	}

}
```

##viewsにadminフォルダーを追加
以下のファイルをAuthの標準機能からコピーして修正
・home.blade.php
・index.blade.php
・login.blade.php
以上のファイルを以下のように変更していく
route('admin.index')　のようにadminを追加
Auth::guard('admin')->check()　ログインチェックをadminに変更
@extends('layouts.app_admin')

##layoutsにapp_admin.blade.phpを追加
例)route('admin.index')　のようにadminを追加
Auth::guard('admin')->check()に変更

ちなみにheadに
```<style>body{background-color:tomato;}</style>```を追加することで標準ログイン機能と一目瞭然で違うとわかりやすくしております。

##Adminモデルを生成
データベースでadminsテーブルを作成したため管理者用のモデルを作成していく

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    use Notifiable;
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

```


参考にした記事
https://qiita.com/PKunito/items/a8300db38ce7d6949106
https://coinbaby8.com/laravel-multi-login.html